Go: A Language Built for Getting Things Done

Go: A Language Built for Getting Things Done

I’m the platform tech lead for the content platform at the Financial Times. We’re building this platform using a microservices architecture. Over the last year, we’ve moved from Java to Go as our default language.

So what led a group of experienced Java programmers to make this jump? Go is an efficient, scalable and productive language that’s also just a little bit boring. Its creators describe it as “a language for programmers who want to get things done.” Our experience is that it’s ideally suited for building simple microservices that communicate using json over http. Read this talk and find out more, including how easy it is to write your first microservice in Go.

A288fb976fc633cde90a2bc19bf2b5a6?s=128

Sarah Wells

October 27, 2016
Tweet

Transcript

  1. 1.

    Go: a language built for getting things done Sarah Wells

    Principal Engineer, Financial Times @sarahjwells
  2. 10.

    @sarahjwells • Started Sept 2007 • Announced and open sourced

    in Nov 2009 • Go 1.0 released March 2012 • Now on version 1.7 (released 2016/08/15) • Both 1.6 and 1.7 releases were mostly changes in the implementation of the toolchain, runtime, and libraries
  3. 12.

    @sarahjwells – Rob Pike keynote at SPLASH 2012 conference “to

    eliminate the slowness and clumsiness of software development at Google, and thereby to make the process more productive and scalable”
  4. 18.

    @sarahjwells • https://golang.org/ • Install Go • Create a workspace

    directory, e.g. go-workspace • set $GOPATH to point to that workspace
  5. 23.
  6. 26.

    @sarahjwells go fmt - formats your code according to specific

    rules • Easier to write • Easier to read • Easier to maintain • Fewer arguments!
  7. 28.

    @sarahjwells FT-MW4708:wosr sarah.wells$ go help Go is a tool for

    managing Go source code. Usage: go command [arguments] The commands are: build compile packages and dependencies clean remove object files doc show documentation for package or symbol env print Go environment information fix run go tool fix on packages fmt run gofmt on package sources
  8. 29.

    @sarahjwells … generate generate Go files by processing source get

    download and install packages and dependencies install compile and install packages and dependencies list list packages run compile and run Go program test test packages tool run specified go tool version print Go version vet run go tool vet on packages
  9. 31.
  10. 35.

    @sarahjwells func split(sum int) (x, y int) { x =

    sum * 4 / 9 y = sum - x return } func main() { x, y := split(15) fmt.Printf("x=%d, y=%d\n", x, y) //outputs x=6, y=9 }
  11. 36.

    @sarahjwells func split(sum int) (x, y int) { x =

    sum * 4 / 9 y = sum - x return } func main() { x, y := split(15) fmt.Printf("x=%d, y=%d\n", x, y) //outputs x=6, y=9 }
  12. 39.

    @sarahjwells package os func Open(name string) (file *File, err error)

    … f, err := os.Open("filename.ext") if err != nil { log.Fatal(err) } // do something with the open *File f
  13. 41.

    @sarahjwells type Rect struct { width int height int }

    func (r Rect) Area() int { return r.width * r.height } func main() { r := Rect{width: 10, height: 5} fmt.Printf("area: %d\n", r.area()) }
  14. 42.

    @sarahjwells type Rectangle struct { width int height int }

    func (r Rectangle) Area() int { return r.width * r.height } func main() { r := Rectangle{width: 10, height: 5} fmt.Printf("area: %d\n", r.Area()) }
  15. 45.

    @sarahjwells package os func (f *File) Write(b []byte) (n int,

    err error) { if f == nil { return 0, ErrInvalid } … }
  16. 46.

    @sarahjwells type ByteCounter struct { counter int } func (c

    *ByteCounter) Write(p []byte) (int, error) { (*c).counter += len(p) return len(p), nil }
  17. 47.

    @sarahjwells package fmt // writes to the supplied writer func

    Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { p := newPrinter() p.doPrintf(format, a) n, err = w.Write(p.buf) p.free() return }
  18. 49.

    @sarahjwells func main() { fmt.Printf("Hello\n") go slowFunction() fmt.Printf("Bye!\n") } func

    slowFunction() { //do something slow time.Sleep(1 * time.Second) fmt.Printf("Finished slow stuff\n") }
  19. 50.

    @sarahjwells ch := make(chan int) ch <- v // Send

    v to channel ch. v := <-ch // Receive from ch, and // assign value to v.
  20. 51.

    @sarahjwells func main() { rand.Seed(time.Now().UnixNano()) responses := make(chan string, 5)

    for i := 1; i <= 5; i++ { go slowFunction(i, responses) } fmt.Printf("Winner was %s\n", <-responses) } func slowFunction(num int, out chan<- string) { waitSeconds := rand.Intn(10) fmt.Printf("Num %d is waiting %d seconds\n", num, waitSeconds) time.Sleep(time.Duration(waitSeconds) * time.Second) out <- fmt.Sprintf("%d", num) }
  21. 52.

    @sarahjwells func main() { rand.Seed(time.Now().UnixNano()) responses := make(chan string, 5)

    for i := 1; i <= 5; i++ { go slowFunction(i, responses) } fmt.Printf("Winner was %s\n", <-responses) } func slowFunction(num int, out chan<- string) { waitSeconds := rand.Intn(10) fmt.Printf("Num %d is waiting %d seconds\n", num, waitSeconds) time.Sleep(time.Duration(waitSeconds) * time.Second) out <- fmt.Sprintf("%d", num) }
  22. 53.

    @sarahjwells func main() { rand.Seed(time.Now().UnixNano()) responses := make(chan string, 5)

    for i := 1; i <= 5; i++ { go slowFunction(i, responses) } fmt.Printf("Winner was %s\n", <-responses) } func slowFunction(num int, out chan<- string) { waitSeconds := rand.Intn(10) fmt.Printf("Num %d is waiting %d seconds\n", num, waitSeconds) time.Sleep(time.Duration(waitSeconds) * time.Second) out <- fmt.Sprintf("%d", num) }
  23. 55.

    @sarahjwells func main() { ah := authorHandler{newHardCodedAuthorService()} r := mux.NewRouter()

    r.HandleFunc("/authors/{uuid}", ah.getAuthor).Methods("GET") http.Handle("/", r) log.Fatal(http.ListenAndServe("localhost:8000", nil)) } type authorHandler struct { as authorService }
  24. 56.

    @sarahjwells func main() { ah := authorHandler{newHardCodedAuthorService()} r := mux.NewRouter()

    r.HandleFunc("/authors/{uuid}", ah.getAuthor).Methods("GET") http.Handle("/", r) log.Fatal(http.ListenAndServe("localhost:8000", nil)) } type authorHandler struct { as authorService }
  25. 57.

    @sarahjwells func (ah *authorHandler) getAuthor(writer http.ResponseWriter, req *http.Request) { vars

    := mux.Vars(req) uuid := vars["uuid"] requestedAuthor, found := ah.as.getAuthorByUUID(uuid) if !found { writer.WriteHeader(http.StatusNotFound) return } enc := json.NewEncoder(writer) //should have error handling here enc.Encode(requestedAuthor) }
  26. 58.

    @sarahjwells type authorService interface { getAuthorByUUID(uuid string) (author, bool) }

    type simpleAuthorService struct { authors map[string]author } func (as simpleAuthorService) getAuthorByUUID(uuid string) (author, bool) { requestedAuthor, found := as.authors[uuid] return requestedAuthor, found }
  27. 59.

    @sarahjwells type author struct { Name string `json:"name"` Email string

    `json:"email"` ImageURL string `json:"imageurl"` Biography string `json:"biography"` TwitterHandle string `json:"twitterhandle"` TmeIdentifier string `json:"tmeidentifier"` }
  28. 61.

    @sarahjwells We’ve talked about: • the language aims • tooling

    • some of the interesting design decisions
  29. 62.

    @sarahjwells So who’s using Go? • Docker is written in

    Go • Dropbox use Go (as well as Python) • Netflix rewrote their chaos monkey in Go
  30. 64.

    @sarahjwells • https://golang.org - the home of Go, including go

    docs • Start with the Go tour: https://tour.golang.org/welcome/1 • Then Effective Go: https://golang.org/doc/effective_go.html • Go by Example: https://gobyexample.com/