The State of Go
Where we are in May 2017

Francesc Campoy
Google Developer Advocate
@francesc
campoy@golang.org

* Recording

A recording of this talk is available [[https://www.youtube.com/watch?v=dyvpF0jF3AY&list=PLtLJO5JKE5YAeVbgwCkgUWyOBsMvZu4UB&index=1][here]].

.image https://img.youtube.com/vi/dyvpF0jF3AY/0.jpg

* Time flies

Go 1.7 is already 9 months old!

Go 1.8 was released on February 16th.

On May 1st we entered the release freeze for Go 1.9

Go 1.9 will be released early August.

.image state-of-go-may/img/flying.png

* Notes

The slides are available on [[/talks/2017/state-of-go-may.slide]]

Most of the code examples won't run except locally and using tip.

The playground runs Go 1.8.

* Agenda

Changes since Go 1.8:

- The Language
- The Standard Library
- The Runtime
- The Tooling
- The Community

* Changes to the language

* Codebase Refactoring (with help from Go)

Article written by Russ Cox [[/talks/2016/refactor.article][link]]

.image state-of-go-may/img/atomic.svg _ 300

* Gradual Code Repair

In reality, atomically changing all usages of an API is often impossible.

.image state-of-go-may/img/gradual.svg _ 600

* An example

Imagine we created a new package `net/http/status`.

First: create the new API

    package status

    const OK = http.StatusOK

Second: change each usage of `http.StatusOK` by `status.OK`.

    if res.StatusCode != http.StatusOK {

    if res.StatusCode != status.OK {

Third: remove the old API

* Another example

Let's rename `http.Get` to `http.DoGetPleaseAndThanks`.

First: create the new API

    func DoGetPleaseAndThanks(url string) (*http.Response, error) {
        return Get(url)
    }

Second: change each usage of `http.Get` to `http.DoGetPleaseAndThanks`.

    res, err := http.Get("https://golang.org")

    res, err := http.DoGetPleaseAndThanks("https://golang.org")

Third: remove the old API

* One last example

Let's move `http.Client` to `http.Applicant`.

First: create the new API

    type Applicant Client

- `Applicant` has no methods.
- Both types are convertible.

    type Applicant struct { Client }

- `Applicant` has all the methods of `Client`
- The types are not convertible.

* Alias declarations

An alias declaration is a new kind of type declaration.

    type Applicant = http.Client

Both types are equivalent and completely interchangeable.

- type conversion is not needed
- can't declare methods on the alias declaration

.play state-of-go-may/alias/main.go /type/,


* Quaternions

.image state-of-go-may/img/quaternions.png _ 750
.caption [[/issue/19813][issue #19813]]

* The Standard library

* A Twitter Poll

.image state-of-go-may/img/twitter-poll.png _ 800
.caption [[https://twitter.com/francesc/status/863514399486623744][twitter poll]]

* math/bits

[[https://tip.golang.org/pkg/math/bits/#Len16][Package bits]] implements bit counting and manipulation functions for the predeclared unsigned integer types.

Added to the standard library with proposal [[/issue/18616][#18616]].

- LenXX, OnesCountXX
- ReverseXX, ReverseBytesXX
- RotateLeftXX
- LeadingZerosXX, TrailingZerosXX

.play state-of-go-may/bits/main.go /START/,/END/

* sync.Map

A new type has been added to the `sync` package with proposal [[/issue/18177][#18177]].

[[https://tip.golang.org/pkg/sync/#Map][sync.Map]] is a concurrent map with amortized-constant-time loads, stores,and deletes.

- the zero map is valid
- it must not be copied (use pointers)

* sync.Map code sample

.play state-of-go-may/syncmap/main.go /func main/,

* html/template panic on predefined escaper

What do you expect [[/play/p/-z5rZilH1F][this code]] to print?

.play state-of-go-may/html/main.go /Foo/,

Predefined escapers in `html` template create a security concern.

Since 1.9 `Execute` will panic.

* os.Exec

Let's imagine that we have a command `getenv` that prints an environment variable
using `os.Getenv`.

.code state-of-go-may/exec/getenv/main.go /func main/,

We can run it as follows:

    $ foo=bar getenv foo
    bar

* os.Exec

What do you expect this code to print?

.code state-of-go-may/exec/main.go /func main/,

bar, or newbar?

* another Twitter poll

.image state-of-go-may/img/exec-poll.png _ 600
.caption [[https://twitter.com/francesc/status/863791506934472705][Twitter poll]]

* os.Exec

`Cmd.Start` now removes duplicates of environment variables, keeping the last one.

This code does what one expects:

    cmd := exec.Command("prog")
    cmd.Env = append(os.Environ(), "FOO=bar")

* The Runtime

* Benchmarks

.image state-of-go-may/img/benchmark.png _ 800
.caption _note_: values over 1.0 mean tip is faster
.caption _note_: unofficial benchmark ran on my laptop while playing YouTube videos

* More runtime

Garbage Collector

- New algorithm for large object allocation
- Better performance and increased determinism for large (+50GB) heaps

[[https://en.wikipedia.org/wiki/DWARF][DWARF]]

- Ongoing effort to improve the generated DWARF information.
- This will help debuggers, among other tools.

* The Tooling

* go compiler: better errors!

Better error messaging for Allman style braces.

    package main

    func main()
    {
        fmt.Println("that ain't gonna compile")
    }

With go 1.8:

    fail/main.go:4: syntax error: unexpected semicolon or newline before {

With go 1.9:

    fail/main.go:3:6: missing function body for "main"
    fail/main.go:4:1: syntax error: unexpected semicolon or newline before {

* go compiler: more modular and faster

The compiler has been refactored into multiple packages.

    cmd/go/internal/...

Issue [[/issue/17639][#17639]] made parsing concurrent.

The compiler is faster as a result.

* go test

`vendor` directories are ignored by the `go` tool [[/issue/19090][#19090]]:

    go test ./...

You can now list all the tests to be executed, without running them [[/issue/17209][#17209]].

	$ go test -test.list .
    TestIntegration
    TestEmbedStreams
    TestEmbedFiles

* godoc

You can now link to fields in a struct in the documentation [[/issue/16753][#16753]].

.link https://tip.golang.org/pkg/net/http/#Client.Transport

_Note_: This was actually introduced with Go 1.8!

* ... and much more!

* The community

* Go meetups

.image state-of-go-may/img/meetups.png _ 900
.caption Gophers all around the world! [[http://go-meetups.appspot.com]]

* Women Who Go

.image state-of-go-may/img/wwg.png _ 800
.caption 19 chapters already! [[http://www.womenwhogo.org]]

* Women Who Go Gophercon Scholarship

WWG is sponsoring minority gophers from all over the world to attend Gophercon

.image state-of-go-may/img/wwg-logo.png _ 700

* Conferences:

- [[http://gophercon.sg][Gophercon Singapore]], May 25-26th
- [[https://gophercon.com/][Gophercon Denver]], Jul 12-15th
- [[http://golanguk.com/][Golang UK]], August 16th-18th
- [[http://2017.dotgo.eu/][dotGo]], Nov 6th
