Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go - a simple programming environment by Andrew Gerrand

Go - a simple programming environment by Andrew Gerrand

Watch the talk here: https://vimeo.com/69237265



April 23, 2013

More Decks by Railsberry

Other Decks in Technology


  1. Go: a simple programming environment 23 April 2013 Andrew Gerrand

  2. Why Go?

  3. Software should be simple

  4. Software can be simple

  5. What I mean by "simple" Small Readable Consistent Orthogonal Predictable

    Robust Useful by default
  6. 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.
  7. The Gopher

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

    Go") } Run
  9. 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
  10. 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!)
  11. 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
  12. 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
  13. 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
  14. 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
  15. html/template The html/template package provides an HTML templating system that

    automatically escapes content depending on its context. const html = ` <script>var foo = {{.Foo}};</script> <a href="{{.URL}}"> {{.Text}} </a> ` 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
  16. 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
  17. An example isgo1point1outyet.com (http://isgo1point1outyet.com)

  18. 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.
  19. 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()
  20. 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 }
  21. 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() }
  22. 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) } }
  23. 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(` <!DOCTYPE html><html><body><center> <h2>Is Go 1.1 out yet?</h2> <h1> {{if .Yes}} <a href="{{.URL}}">YES!</a> {{else}} No. {{end}} </h1> </center></body></html> `))
  24. 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.
  25. Demo

  26. One more thing

  27. 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
  28. 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)
  29. Demo

  30. Conclusion Simplicity revisited: Small Readable Consistent Orthogonal Predictable Robust Useful

    by default
  31. 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
  32. 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)
  33. Thank you 23 April 2013 Andrew Gerrand Google @enneff (http://twitter.com/enneff)

    adg@golang.org (mailto:adg@golang.org) http://golang.org (http://golang.org)