Подтвердить что ты не робот

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

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

Теперь, что вы собираетесь с ним делать?

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

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

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

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

4b9b3361

Ответ 1

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

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 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)
}

Ответ 2

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

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))
}

Ответ 3

Хорошо, я верну мяч. Вот моя первая программа 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 

Ответ 4

Мне очень нравятся каналы 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
      }
    }
  }
}

Ответ 5

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

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
        } 
        }
}