Search code examples
godemo

What can you do in 30 lines of Go? Can you create a useful, complete program that demonstrates its features?


So, the big buzz in the last few days is Go, the new language from Google. Assuming you're all obsessive programming language geeks like me, you've all downloaded it, built it, and run your "Hello, 世界" program (isn't it nice using a language written by the inventors of UTF-8?). You've all read the tutorial, Effective Go, and some of the other docs.

Now, what are you going to do with it?

I'd like to see some demos that show off the power of Go. What can you do in a brief program? Show off your best example code. While the true measure of a language can't really be taken until you've written and maintained a large codebase with a team of many programmers over the course of a project with changing requirements, seeing how much you can do in a limited amount of code does help to demonstrate the expressive power of a language. I'd like to see short, complete programs that truly exercise the unique new features of Go; not just snippets or "Hello, World".

So, post some cool code you've written with Go. Take advantage of its unique features, like its goroutines and channels for concurrency, or its interface based type system. Can you write a primitive chat server, or cool IRC bot? Implement a parallel Mandelbrot set that scales to many cores? Write an interpreter for some tiny language? And can you do it all in 30 lines?

I chose 30 arbitrarily as about as much as you can fit into a Stack Overflow code block without it overflowing and getting a scroll bar; it should be enough to do something interesting without golfing too much, but short enough to keep everyone's attention for a quick demo. For instance, with just a bit of reformatting, the example web server should be able to fit (not counting the data).

Show us your Go code!


Solution

  • This makes a PNG (on stdout) of a clock face showing the current time. It's barely golfed to fit thirty lines, so the code is not quite as clean as it should be.

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

    Run it like

    8.out > clock.png
    

    Notice all those float64 casts? I've NEVER seen a language as strict as Go about types.


    This is the same code fixed with go fix (and some manual tweaking) and then automatically formatted using go fmt. Some newlines where inserted manually.

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