Slide 1

Slide 1 text

Go: a simple programming environment 23 April 2013 Andrew Gerrand Google

Slide 2

Slide 2 text

Why Go?

Slide 3

Slide 3 text

Software should be simple

Slide 4

Slide 4 text

Software can be simple

Slide 5

Slide 5 text

What I mean by "simple" Small Readable Consistent Orthogonal Predictable Robust Useful by default

Slide 6

Slide 6 text

Go at a glance Compiled Statically typed Clean syntax Simple type system Concurrency primitives Rich standard library Great tools Open source This talk is just a taste.

Slide 7

Slide 7 text

The Gopher

Slide 8

Slide 8 text

Hello, Go package main import "fmt" func main() { fmt.Println("Hello, Go") } Run

Slide 9

Slide 9 text

go Goroutines are lightweight threads that are managed by the Go runtime. To run a function in a new goroutine, just put "go" before the function call. package main import ( "fmt" "time" ) func main() { go say("let's go!", 3*time.Second) go say("ho!", 2*time.Second) go say("hey!", 1*time.Second) time.Sleep(4 * time.Second) } func say(text string, delay time.Duration) { time.Sleep(delay) fmt.Println(text) } Run

Slide 10

Slide 10 text

chan Channels are typed conduits for sychronization and communication between goroutines. They're a versatile and expressive means of modelling concurrent processes. But we're not going to look at them today. (There's no time!)

Slide 11

Slide 11 text

sync Channels are great, but sometimes other concurrency mechanisms are a better fit. The sync package provides mutexes, condition variables, and more useful primitives. func main() { wg := new(sync.WaitGroup) wg.Add(3) go say(wg, "let's go!", 3*time.Second) go say(wg, "ho!", 2*time.Second) go say(wg, "hey!", 1*time.Second) wg.Wait() } func say(wg *sync.WaitGroup, text string, delay time.Duration) { time.Sleep(delay) fmt.Println(text) wg.Done() } Run

Slide 12

Slide 12 text

time The time package provides Time and Duration types, for expressing instants in time and periods of time. It also provides a Location type for expressing time zones. And, as we've already seen, it provides functions related to sleeping. birthday, _ := time.Parse("Jan 2 2006", "Nov 10 2009") // time.Time age := time.Since(birthday) // time.Duration fmt.Printf("Go is %d days old\n", age/(time.Hour*24)) Run t := time.Now() fmt.Println(t.In(time.UTC)) home, _ := time.LoadLocation("Australia/Sydney") fmt.Println(t.In(home)) Run

Slide 13

Slide 13 text

net/http (1/2) The net/http package provides an HTTP client. The client handles HTTP Keep-Alive using a pool of connections, by default. (This is configurable, of course.) func main() { r, err := http.Get("http://www.golang.org/") if err != nil { log.Fatal(err) } if r.StatusCode != http.StatusOK { log.Fatal(r.Status) } io.Copy(os.Stdout, r.Body) } Run

Slide 14

Slide 14 text

net/http (2/2) The net/http package also provides an HTTP server. This is a high-performance, DoS-hardened, production-ready web server. It serves dl.google.com. func main() { http.HandleFunc("/", handler) err := http.ListenAndServe("localhost:8080", nil) if err != nil { log.Fatal(err) } } func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello, web") } Run

Slide 15

Slide 15 text

html/template The html/template package provides an HTML templating system that automatically escapes content depending on its context. const html = ` var foo = {{.Foo}}; {{.Text}} ` func main() { tmpl := template.Must(template.New("example").Parse(html)) data := struct { Foo string URL, Text string }{ Foo: `Some "quoted" string`, URL: `" onClick="alert('xss!');`, Text: "The <- operator is for channel sends and receives", } tmpl.Execute(os.Stdout, data) } Run

Slide 16

Slide 16 text

flag The flag package provides a simple API for parsing command-line flags. Example invocation (a little different than GNU getopt): $ flag -message 'Hold on...' -delay 5m var ( message = flag.String("message", "Hello!", "what to say") delay = flag.Duration("delay", 2*time.Second, "how long to wait") ) func main() { flag.Parse() fmt.Println(*message) time.Sleep(*delay) } Run

Slide 17

Slide 17 text

An example isgo1point1outyet.com (http://isgo1point1outyet.com)

Slide 18

Slide 18 text

Structure The program has two parts that execute concurrently: a poller that continuously checks whether Go 1.1 has been tagged, and an HTTP server providing the user interface.

Slide 19

Slide 19 text

Sharing state We must share state ("Is Go 1.1 out?") between the repo poller and the user interface. This global struct variable contains a sync.RWMutex and a boolean value: var state struct { sync.RWMutex yes bool // whether Go 1.1 has been tagged. } To read, take the read lock (multiple goroutines can do this simultaneously): state.RLock() yes := state.yes state.RUnlock() To write, take the write lock (only one goroutine can do this at a time): state.Lock() state.yes = true state.Unlock()

Slide 20

Slide 20 text

Polling (1/2) When a go1.1 tag exists in the Go repository this URL will return a "200 OK" response: const changeURL = "https://code.google.com/p/go/source/detail?r=go1.1" The isTagged function returns true if the go1.1 tag exists. func isTagged() bool { r, err := http.Head(changeURL) if err != nil { log.Print(err) return false } return r.StatusCode == http.StatusOK }

Slide 21

Slide 21 text

Polling (2/2) The poll function loops until isTagged returns true. Then it updates the state ("Go 1.1 is out!") and returns. func poll(period time.Duration) { for !isTagged() { time.Sleep(period) } state.Lock() state.yes = true state.Unlock() }

Slide 22

Slide 22 text

Serving the user interface The handler function serves an HTTP request. It puts the state.yes and changeURL values into a struct, and uses the struct to render the template as the HTTP response. func handler(w http.ResponseWriter, r *http.Request) { state.RLock() data := struct { Yes bool URL string }{ Yes: state.yes, URL: changeURL, } state.RUnlock() err := tmpl.Execute(w, data) if err != nil { log.Print(err) } }

Slide 23

Slide 23 text

The HTML user interface The tmpl variable is a template that provides the HTML UI. It is a global variable, so the template is parsed just once at init time. var tmpl = template.Must(template.New("root").Parse(`

Is Go 1.1 out yet?

{{if .Yes}} YES! {{else}} No. {{end}}

`))

Slide 24

Slide 24 text

Putting it all together The main function starts polling in a new goroutine and sets up the web server. Some command-line flags enable run time configuration. var ( httpAddr = flag.String("http", "localhost:8080", "Listen address") pollPeriod = flag.Duration("poll", 5*time.Second, "Poll period") ) func main() { flag.Parse() go poll(*pollPeriod) http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(*httpAddr, nil)) } The whole program is just 68 lines of code.

Slide 25

Slide 25 text

Demo

Slide 26

Slide 26 text

One more thing

Slide 27

Slide 27 text

expvar (1/2) The expvar package allows you to export variables via an HTTP handler registered at /debug/vars (http://localhost:8080/debug/vars) . package main import ( "expvar" "log" "net/http" "time" ) func main() { count := expvar.NewInt("count") go func() { for { count.Add(1) time.Sleep(time.Second) } }() log.Fatal(http.ListenAndServe("localhost:8080", nil)) } Run

Slide 28

Slide 28 text

expvar (1/2) var ( hitCount = expvar.NewInt("hitCount") pollCount = expvar.NewInt("pollCount") pollError = expvar.NewString("pollError") pollErrorCount = expvar.NewInt("pollErrorCount") ) func isTagged() bool { pollCount.Add(1) r, err := http.Head(changeURL) if err != nil { log.Print(err) pollError.Set(err.Error()) pollErrorCount.Add(1) return false } return r.StatusCode == http.StatusOK } func handler(w http.ResponseWriter, r *http.Request) { hitCount.Add(1)

Slide 29

Slide 29 text

Demo

Slide 30

Slide 30 text

Conclusion Simplicity revisited: Small Readable Consistent Orthogonal Predictable Robust Useful by default

Slide 31

Slide 31 text

Stuff I didn't talk about Types and interfaces Concurrency in depth Packages and the build system Code formatting Testing Benchmarking and profiling Debugging Documentation

Slide 32

Slide 32 text

Learn more about Go The Go web site golang.org (http://golang.org) The Go blog blog.golang.org (http://blog.golang.org) Go talks talks.golang.org (http://talks.golang.org) A Tour of Go tour.golang.org (http://tour.golang.org)

Slide 33

Slide 33 text

Thank you 23 April 2013 Andrew Gerrand Google @enneff (http://twitter.com/enneff) [email protected] (mailto:[email protected]) http://golang.org (http://golang.org)