40

因此,最近几天的热门话题是Google 的新语言Go。假设你们都是像我一样痴迷的编程语言极客,你们都已经下载、构建并运行了“Hello, 世界”程序(使用 UTF-8 的发明者编写的语言不是很好吗?) . 你们都阅读了教程Effective Go和其他一些文档。

现在,你打算用它做什么?

我想看一些展示 Go 强大功能的演示。你可以在一个简短的程序中做什么?展示你最好的示例代码。虽然在需求不断变化的项目过程中,与许多程序员组成的团队一起编写和维护大型代码库之前,才能真正衡量一门语言,看看在有限的代码中可以做多少代码确实有助于展示一种语言的表达能力。我希望看到能够真正发挥 Go 独特新功能的简短、完整的程序;不仅仅是片段或“你好,世界”。

所以,发布一些你用 Go 编写的很酷的代码。利用其独特的功能,例如用于并发的 goroutine 和通道,或基于接口的类型系统。你能写一个原始的聊天服务器,或者很酷的 IRC 机器人吗?实现一个可扩展到多核的并行 Mandelbrot 集?为一些小语言写一个解释器?你能在 30 行内全部完成吗?

我任意选择了 30 个,尽可能多地放入 Stack Overflow 代码块中,而不会溢出并获得滚动条;它应该足以在不打太多高尔夫球的情况下做一些有趣的事情,但又足够短以保持每个人的注意力以进行快速演示。例如,只需重新格式化,示例Web 服务器应该能够适应(不计算数据)。

向我们展示您的 Go 代码!

4

5 回答 5

12

这是我编写的一个 Web 代理,用于提供对需要 HTTP 基本身份验证的 Web 服务的未经身份验证的访问。我需要它用于内部事物(并且仍在使用它):

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))
}
于 2012-05-23T19:43:59.403 回答
8

这使得钟面的 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 > 时钟.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)
}
于 2009-11-16T06:09:06.490 回答
4

好的,我会让球滚动。这是我的第一个 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.6
$ ./服务器

然后在其他几个终端中,连接

$ 数控本地主机 4242 
于 2009-11-16T01:37:44.250 回答
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
      }
    }
  }
}
于 2012-05-23T14:09:43.000 回答
-1

我从某个地方复制了这个。相当简单,但显示了一些功能。

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
        } 
        }
}
于 2011-05-04T13:39:54.800 回答