| Go: a simple programming environment |
| |
| 9 Nov 2012 |
| |
| # Go is a general-purpose language that bridges the gap between efficient |
| # statically typed languages and productive dynamic language. But it’s not just |
| # the language that makes Go special – Go has broad and consistent standard |
| # libraries and powerful but simple tools. |
| # |
| # This talk gives an introduction to Go, followed by a tour of some real |
| # programs that demonstrate the power, scope, and simplicity of the Go |
| # programming environment. |
| |
| Andrew Gerrand |
| Google Inc. |
| @enneff |
| adg@golang.org |
| http://golang.org |
| |
| * Video |
| |
| A video of this talk was recorded at Øredev in Malmö, Sweden in November 2012. |
| |
| .link http://vimeo.com/53221558 Watch the talk on Vimeo |
| |
| * Background |
| |
| * Why a new language? |
| |
| Motivated by our needs at Google. |
| |
| We need: |
| |
| - Efficiency |
| - Safety |
| - Concurrency |
| - Scalability |
| - Fast development cycle |
| - No surprises |
| - A cute mascot |
| |
| * Design |
| |
| "Consensus drove the design. Nothing went into the language until [Ken Thompson, Robert Griesemer, and myself] all agreed that it was right. Some features didn’t get resolved until after a year or more of discussion." - Rob Pike |
| |
| Go is: |
| |
| - Lightweight, avoids unnecessary repetition |
| - Object Oriented, but not in the usual way |
| - Concurrent, in a way that keeps you sane |
| - Designed for working programmers |
| |
| * Go 1 |
| |
| Released in March 2012 |
| |
| A specification of the language and libraries that will be supported for years. |
| |
| The guarantee: code written for Go 1.0 will build and run with Go 1.x. |
| |
| Best thing we ever did. |
| |
| * The gopher |
| |
| .image simple/gopher.jpg |
| |
| * Hello, go |
| |
| .play simple/hello.go |
| |
| * Standard library |
| |
| * Packages |
| |
| Go code lives in packages. |
| |
| Packages contain type, function, variable, and constant declarations. |
| |
| Packages can be very small (package `errors` has just one declaration) or very large (package `net/http` has >100 declarations). Most are somewhere in between. |
| |
| Case determines visibility: `Foo` is exported, `foo` is not |
| |
| * io |
| |
| The `io` package provides fundamental I/O interfaces that are used throughout most Go code. |
| |
| The most ubiquitous are the `Reader` and `Writer` types, which describe streams of data. |
| |
| .code simple/io/io.go |
| |
| `Reader` and `Writer` implementations include files, sockets, (de)compressors, image and JSON codecs, and many more. |
| |
| * Chaining io.Readers |
| |
| .play simple/reader.go |
| |
| * net/http |
| |
| The `net/http` package implements an HTTP server and client. |
| |
| .play simple/hello-web.go |
| |
| * encoding/json |
| |
| The `encoding/json` package converts JSON-encoded data to and from native Go data structures. |
| |
| .play simple/json.go /const/,$ |
| |
| * time |
| |
| The `time` package provides a representation of time and duration, and other time-related functions. |
| |
| .play simple/time.go /START/,/END/ |
| .play simple/time2.go /START/,/END/ |
| |
| `time.Time` values also contain a `time.Location` (for display only): |
| |
| .play simple/time3.go /START/,/END/ |
| |
| * flag |
| |
| The `flag` package provides a simple API for parsing command-line flags. |
| |
| .play simple/flag.go |
| |
| $ flag -message 'Hold on...' -delay 5m |
| |
| * Tools |
| |
| * The go tool |
| |
| The `go` tool is the de facto standard for building and installing Go code. |
| |
| Compile and run a single-file program: |
| |
| $ go run hello.go |
| |
| Build and install the package in the current directory (and its dependencies): |
| |
| $ go install |
| |
| Build and install the `fmt` package (and its dependencies): |
| |
| $ go install fmt |
| |
| This tool also acts as an interface for most of the Go tools. |
| |
| * Import paths |
| |
| The `go` tool is a "zero configuration" tool. No Makefiles or scripts. Just Go code. |
| Your build schema and code are always in sync; they are one and the same. |
| |
| Package import paths mirror the code's location in the file system: |
| |
| src/ |
| github.com/nf/ |
| gosynth/ |
| main.go |
| note.go |
| osc.go |
| wav/ |
| writer.go |
| |
| The `gosynth` program imports the `wav` package: |
| |
| import "github.com/nf/wav" |
| |
| Installing `gosynth` will automatically install the `wav` package: |
| |
| $ go install github.com/nf/gosynth |
| |
| * Remote dependencies |
| |
| The `go` tool also fetches Go code from remote repositories. |
| |
| Import paths can be URLs: |
| |
| import "golang.org/x/net/websocket" |
| |
| To fetch, build and install a package: |
| |
| $ go get code.google.com/p/go.net/websocket |
| |
| To fetch, build, and install `gosynth` and its dependencies: |
| |
| $ go get github.com/nf/gosynth |
| |
| This simple design leads to other cool tools: |
| |
| .link http://go.pkgdoc.org |
| |
| * Godoc |
| |
| Godoc extracts documentation from Go code and presents it in a variety of forms. |
| |
| Comments need no special format, they just need to precede what they document. |
| |
| // Split slices s into all substrings separated by sep and returns a slice of |
| // the substrings between those separators. |
| // If sep is empty, Split splits after each UTF-8 sequence. |
| // It is equivalent to SplitN with a count of -1. |
| func Split(s, sep string) []string { |
| |
| .image simple/split.png |
| |
| Documentation that lives with code is easy to keep up-to-date. |
| |
| * Gofmt |
| |
| The `gofmt` tool is a pretty-printer for Go source code. |
| |
| All Go code in the core is gofmt'd, as is ~70% of open source Go code. |
| |
| Ends boring formatting discussions. |
| |
| Improves readability. Improves writability. |
| |
| Saves a _huge_ amount of time. |
| |
| * Tests: writing |
| |
| The `go` tool and the `testing` package provide a lightweight test framework. |
| |
| .code simple/test/string_test.go /func TestIndex/,/^}/ |
| |
| * Tests: running |
| |
| The go tool runs tests. |
| |
| $ go test |
| PASS |
| |
| $ go test -v |
| === RUN TestIndex |
| --- PASS: TestIndex (0.00 seconds) |
| PASS |
| |
| To run the tests for all my projects: |
| |
| $ go test github.com/nf/... |
| |
| * Tests: benchmarks |
| |
| The `testing` package also supports benchmarks. |
| |
| A sample benchmark function: |
| |
| .code simple/test/string_test.go /func BenchmarkIndex/,/^}/ |
| |
| The benchmark package will vary `b.N` until the benchmark function lasts long enough to be timed reliably. |
| |
| $ go test -test.bench=Index |
| PASS |
| BenchmarkIndex 50000000 37.3 ns/op |
| |
| * Tests: doc examples |
| |
| The `testing` package also supports testable examples. |
| |
| .code simple/test/string_test.go /func ExampleIndex/,/^}/ |
| |
| Examples and built and run as part of the normal test suite: |
| |
| $ go test -v |
| === RUN: ExampleIndex |
| --- PASS: ExampleIndex (0.00 seconds) |
| PASS |
| |
| The example is displayed in `godoc` alongside the thing it demonstrates: |
| |
| .link http://golang.org/pkg/strings/#Index |
| |
| * And there's more |
| |
| - `vet`: checks code for common programmer mistakes |
| - `pprof`: CPU and memory profiling |
| - `fix`: automatically migrate code as APIs change |
| - GDB support |
| - Editor support: Vim, Emacs, Eclipse, Sublime Text |
| |
| * An example |
| |
| * Webfront |
| |
| `Webfront` is an HTTP server and reverse proxy. |
| |
| It reads a JSON-formatted rule file like this: |
| |
| .code simple/webfront/main.go /^\[/,/\]/ |
| |
| For all requests to the host `example.com` (or any name ending in `".example.com"`) it serves files from the `/var/www` directory. |
| |
| For requests to `example.org`, it forwards the request to the HTTP server listening on localhost port 8080. |
| |
| * The Rule type |
| |
| A `Rule` value specifies what to do for a request to a specific host. |
| |
| .code simple/webfront/main.go /Rule represents/,/^}/ |
| |
| It corresponds directly with the entries in the JSON configuration file. |
| |
| .code simple/webfront/main.go /^\[/,/\]/ |
| |
| * Rule methods |
| |
| .code simple/webfront/main.go /Match returns/,/^}/ |
| .code simple/webfront/main.go /Handler returns/,/^}/ |
| |
| * The Server type |
| |
| The `Server` type is responsible for loading (and refreshing) the rules from the rule file and serving HTTP requests with the appropriate handler. |
| |
| .code simple/webfront/main.go /Server implements/,/^}/ |
| .code simple/webfront/main.go /ServeHTTP matches/,/^}/ |
| |
| * The handler method |
| |
| .code simple/webfront/main.go /handler returns/,/^}/ |
| |
| * Parsing rules |
| |
| The `parseRules` function uses the `encoding/json` package to read the rule file into a Go data structure. |
| |
| .code simple/webfront/main.go /parseRules reads/,/^}/ |
| |
| * The loadRules method |
| |
| .code simple/webfront/main.go /loadRules tests/,/^}/ |
| |
| * Constructing the server |
| |
| .code simple/webfront/main.go /NewServer constructs/,/^}/ |
| |
| This constructor function launches a goroutine running the `refreshRules` method. |
| |
| * Refreshing the rules |
| |
| .code simple/webfront/main.go /refreshRules polls/,/^}/ |
| |
| * Bringing it all together |
| |
| The main function parses command-line flags, constructs a `Server`, and launches an HTTP server that serves all requests with the `Server`. |
| |
| .code simple/webfront/main.go /^var/,/^}/ |
| |
| * Demo |
| |
| * Testing (1/3) |
| |
| The `Server` integration test uses the `httptest` package to construct a dummy HTTP server, synthesizes a set of rules, and constructs a `Server` instance that uses those rules. |
| |
| .code simple/webfront/server_test.go /^func testHandler/,/STOP/ |
| |
| * Testing (2/3) |
| |
| Each test case in the table specifies a request URL and the expected response code and body. |
| |
| .code simple/webfront/server_test.go /TESTS START/,/STOP/ |
| |
| * Testing (3/3) |
| |
| For each test case, construct an `http.Request` for the url and an `httptest.ResponseRecorder` to capture the response, and pass them to the `Server.ServeHTTP` method. Then check that the response matches the test case. |
| |
| .code simple/webfront/server_test.go /RANGE START/,/^}/ |
| |
| * Demo |
| |
| * Conclusions |
| |
| * Further reading |
| |
| All about Go: |
| |
| .link http://golang.org |
| |
| The slides for this talk: |
| |
| .link http://go.dev/talks/2012/simple.slide |
| |
| webfront: |
| |
| .link https://github.com/nf/webfront |
| |