blob: f5312be99906f71438e879ee07912df8cbef4983 [file] [log] [blame]
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.
* Video
A video of this talk was recorded at Øredev in Malmö, Sweden in November 2012.
.link 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:
The `gosynth` program imports the `wav` package:
import ""
Installing `gosynth` will automatically install the `wav` package:
$ go install
* Remote dependencies
The `go` tool also fetches Go code from remote repositories.
Import paths can be URLs:
import ""
To fetch, build and install a package:
$ go get
To fetch, build, and install `gosynth` and its dependencies:
$ go get
This simple design leads to other cool tools:
* 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
$ go test -v
=== RUN TestIndex
--- PASS: TestIndex (0.00 seconds)
To run the tests for all my projects:
$ go test
* 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
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)
The example is displayed in `godoc` alongside the thing it demonstrates:
* 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 `` (or any name ending in `""`) it serves files from the `/var/www` directory.
For requests to ``, 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:
The slides for this talk: