Что вы можете сделать за 30 строк Go?Можете ли вы создать полезную, полноценную программу, демонстрирующую ее возможности?[закрыто]

StackOverflow https://stackoverflow.com/questions/1735073

  •  20-09-2019
  •  | 
  •  

Вопрос

Итак, самый большой ажиотаж в последние несколько дней вызван Вперед, новый язык от Google.Предполагая, что вы все такие же одержимые фанаты языка программирования, как я, вы все скачали его, собрали и запустили свою программу "Hello, 世界" (разве не приятно использовать язык, написанный изобретателями UTF-8?).Вы все читали учебное пособие, Эффективный Переход, и некоторые другие документы.

Итак, что ты собираешься с этим делать?

Я бы хотел посмотреть несколько демо-версий, которые демонстрируют мощь Go.Что вы можете сделать в краткой программе?Покажите свой лучший пример кода.Хотя истинную оценку языка невозможно оценить, пока вы не напишете и не будете поддерживать большую кодовую базу с командой из многих программистов в ходе проекта с меняющимися требованиями, представление о том, как много вы можете сделать в ограниченном объеме кода, помогает продемонстрировать выразительную силу языка.Я хотел бы видеть короткие, полные программы, которые действительно используют уникальные новые возможности Go;не просто фрагменты или "Привет, мир".

Итак, опубликуйте какой-нибудь классный код, который вы написали с помощью Go.Воспользуйтесь преимуществами его уникальных функций, таких как его программы и каналы для параллелизма или его система типов на основе интерфейса.Можете ли вы написать примитивный чат-сервер или классного IRC-бота?Реализовать параллельный набор Мандельброта, который масштабируется до многих ядер?Написать переводчик для какого-нибудь крошечного языка?И можете ли вы сделать все это в 30 строках?

Я произвольно выбрал 30, примерно столько, сколько вы можете поместить в блок кода переполнения стека без его переполнения и получения полосы прокрутки;этого должно быть достаточно, чтобы сделать что-то интересное, не слишком увлекаясь игрой в гольф, но достаточно короткое, чтобы привлечь всеобщее внимание к быстрой демонстрации.Например, при небольшом переформатировании пример веб-сервер должно быть в состоянии поместиться (не считая данных).

Покажите нам свой Go-код!

Это было полезно?

Решение

Это создает PNG (на стандартном выводе) циферблата часов, показывающего текущее время.Он едва вмещает тридцать строк, так что код не такой чистый, каким должен быть.

package main
import ("image"; "image/png"; "math"; "bufio"; "os"; "time")
const clock_size = 200;
const radius = clock_size / 3;
var colour image.RGBAColor;
func circle (clock *image.RGBA) {
    for angle := float64(0); angle < 360; angle++ {
        radian_angle := math.Pi * 2 * angle / 360;
        x := radius * math.Sin (radian_angle) + clock_size/2;
        y := radius * math.Cos (radian_angle) + clock_size/2;
        clock.Set (int (x), int (y), colour);}}
func hand (clock *image.RGBA, angle float64, length float64) {
    radian_angle := math.Pi * 2 * angle;
    x_inc := math.Sin (radian_angle);
    y_inc := -math.Cos (radian_angle);
    for i := float64(0); i < length; i++ {
        x := i * x_inc + clock_size/2;
        y := i * y_inc + clock_size/2;
        clock.Set (int (x), int (y), colour);}}
func main () {
    clock := image.NewRGBA (clock_size, clock_size);
    colour.A = 255;
    circle (clock);
    time := time.LocalTime ();
    hand (clock, (float64(time.Hour) + float64(time.Minute)/60)/12, radius*0.6); // hour hand
    hand (clock, (float64(time.Minute) + float64(time.Second)/60)/60, radius*0.8); // minute hand
    out := bufio.NewWriter(os.Stdout);
    defer out.Flush();
    png.Encode(out, clock);
}

Запустите это как

8.out > clock.png

Заметили все эти приведения float64?Я НИКОГДА не видел такого строгого языка, как Go о типах.


Это тот же самый код, исправленный с помощью go fix (и некоторая ручная настройка), а затем автоматически форматируется с помощью go fmt.Некоторые новые строки были вставлены вручную.

package main

import (
    "bufio"
    "image"
    "image/color"
    "image/png"
    "math"
    "os"
    "time"
)

const clock_size = 200
const radius = clock_size / 3

var colour color.RGBA

func circle(clock *image.RGBA) {
    for angle := float64(0); angle < 360; angle++ {
        radian_angle := math.Pi * 2 * angle / 360
        x := radius*math.Sin(radian_angle) + clock_size/2
        y := radius*math.Cos(radian_angle) + clock_size/2
        clock.Set(int(x), int(y), colour)
    }
}

func hand(clock *image.RGBA, angle float64, length float64) {
    radian_angle := math.Pi * 2 * angle
    x_inc := math.Sin(radian_angle)
    y_inc := -math.Cos(radian_angle)
    for i := float64(0); i < length; i++ {
        x := i*x_inc + clock_size/2
        y := i*y_inc + clock_size/2
        clock.Set(int(x), int(y), colour)
    }
}

func main() {
    clock := image.NewRGBA(image.Rect(0, 0, clock_size, clock_size))
    colour.A = 255
    circle(clock)
    time := time.Now()
    hand(clock, (float64(time.Hour())+float64(time.Minute())/60)/12, radius*0.6)   // hour hand
    hand(clock, (float64(time.Minute())+float64(time.Second())/60)/60, radius*0.8) // minute hand
    out := bufio.NewWriter(os.Stdout)
    defer out.Flush()
    png.Encode(out, clock)
}

Другие советы

Это веб-прокси, который я написал для предоставления неаутентифицированного доступа к веб-сервису, для которого требуется HTTP basic auth.Мне это было нужно для внутренней штуковины (и я все еще использую ее).:

package main

import (
    "flag"
    "log"
    "net/http"
    "net/url"
)

var target = flag.String("target", "http://www.google.com/", "Where to go.")
var addr = flag.String("listen", ":12345", "Address/port on which to listen.")
var auth = flag.String("auth", "", "Authorization header to add (optional).")

func main() {
    flag.Parse()

    targetUrl, uerr := url.Parse(*target)
    if uerr != nil {
        log.Fatalf("Error parsing target ``%s'': ", target, uerr.String())
    }

    proxy := http.ReverseProxy{Director: func(req *http.Request) {
        req.URL.Scheme = targetUrl.Scheme
        req.URL.Host = targetUrl.Host
        req.Host = targetUrl.Host
        if *auth != "" {
            req.Header.Set("Authorization", *auth)
        }
    }}

    log.Fatal(http.ListenAndServe(*addr, &proxy))
}

Хорошо, я начну действовать.Вот моя первая программа Go.Это очень примитивный чат-сервер, и он умещается в 30 строках по 80 символов, если я немного сжму его;отформатированный с gofmt, это 60 строк.Он прослушивает жестко закодированный порт (4242), практически не обрабатывает ошибки и не обрабатывает отключение клиента, за исключением прекращения попыток чтения с клиента, если он получает ошибку.

package main
import ("net";"container/vector";"bufio";"strings")
type client struct { conn net.Conn; send chan string; receive chan string }
func main() {
    if listener, err := net.Listen("tcp", "0.0.0.0:4242"); err == nil {
        master := make(chan string, 100);
        clients := vector.New(0);
        go runServer(master, clients);
        for {
            if conn, err := listener.Accept(); err == nil {
                c := client{ conn, master, make(chan string, 100) };
                clients.Push(c);
                go runClient(c);
            } else { break } } } }
func runServer(master chan string, clients *vector.Vector) {
    for { 
        message := <-master;
        clients.Do(func (c interface{}) { c.(client).receive <- message }); } }
func runClient(c client) {
    input := make(chan string, 10);
    go readLines(c, input);
    for {
        select {
        case inMessage := <-input: c.send <- inMessage;
        case outMessage := <-c.receive: c.conn.Write(strings.Bytes(outMessage));
        } } }
func readLines(c client, input chan string) {
    reader := bufio.NewReader(c.conn);
    for { if line, err := reader.ReadString('\n'); err == nil 
            { input <- line; } else { break } } }

Создавайте и запускайте с:

$ 6g server.go
$ 6l -o server server.6
$ ./server

А затем на нескольких других терминалах соединитесь с

$ nc localhost 4242 

Мне действительно нравятся каналы go и select утверждение, итак, вот кое-что, что показывает, как легко выразить концепцию "пойти и получить как можно больше вещей за определенное время".

Это генерирует как можно больше случайных чисел в течение 300 миллисекунд и возвращает самое большое число, сгенерированное за это время.

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func main() {
  timeout := time.After(300 * time.Millisecond)
  numbers := make(chan int) // This channel will be used 
  var numberCount int = 0
  var maxNumber int = 0

  // Start putting random numbers on the numbers channel
  go func() {
    for {
      numbers <- rand.Int()
    }
  }()

  for {
    select {
    case <- timeout:
      fmt.Printf("%v numbers generated. Max number found: %v.\n", numberCount, maxNumber)
      return

    case number := <- numbers:
      numberCount++
      if number > maxNumber {
        maxNumber = number
      }
    }
  }
}

Я откуда-то скопировал это.Довольно простой, но обладает некоторыми особенностями.

package main
import ("fmt"; "os" ;"bufio";"io")
func main() {
        if len(os.Args) < 2 {
                fmt.Printf("usage: catfile \n")
        } else if pFile, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0); err != nil {
                fmt.Printf("error opening file : %s\n", err)
        } else {
            defer pFile.Close()
        displayFile(pFile)
    }
}

func displayFile(pFile *os.File) {
        oReader := bufio.NewReader(pFile);
        for {
                if sLine, err := oReader.ReadString('\n'); err == nil {
            fmt.Printf("%s", sLine)
        } else {
            if err != io.EOF {fmt.Printf("error reading file : %s\n", err)}
                    break
        } 
        }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top