The State of Go

Where we are in May 2017

Francesc Campoy

Google Developer Advocate

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.

Notes

The slides are available on talks.golang.org/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:

Changes to the language

Codebase Refactoring (with help from Go)

Article written by Russ Cox link

Gradual Code Repair

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

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
type Applicant struct { Client }

Alias declarations

An alias declaration is a new kind of type declaration.

type Applicant = http.Client

Both types are equivalent and completely interchangeable.

// +build go1.9

package main

import (
	"fmt"
	"net/http"
)

type Applicant = http.Client

func main() {
    fmt.Printf("%T", Applicant{})
}

Quaternions

issue #19813

The Standard library

A Twitter Poll

twitter poll

math/bits

Package bits implements bit counting and manipulation functions for the predeclared unsigned integer types.

Added to the standard library with proposal #18616.

// +build go1.9

package main

import (
	"fmt"
	"math/bits"
)

func main() {
	const n = 100
    fmt.Printf("%d (%b) has %d bits set to one\n", n, n, bits.OnesCount(n))

    fmt.Printf("%d reversed is %d\n", n, bits.Reverse(n))

    fmt.Printf("%d can be encoded in %d bits\n", n, bits.Len(n))
}

sync.Map

A new type has been added to the sync package with proposal #18177.

sync.Map is a concurrent map with amortized-constant-time loads, stores,and deletes.

sync.Map code sample

// +build go1.9

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
    var m sync.Map

    for i := 0; i < 3; i++ {
        go func(i int) {
            for j := 0; ; j++ {
                m.Store(i, j)
            }
        }(i)
    }

    for i := 0; i < 10; i++ {
        m.Range(func(key, value interface{}) bool {
            fmt.Printf("%d: %d\t", key, value)
            return true
        })
        fmt.Println()
        time.Sleep(time.Second)
    }
}

html/template panic on predefined escaper

What do you expect this code to print?

package main

import (
	"html/template"
	"log"
	"os"
)

type Foo struct{ Bar string }

func main() {
    tmpl, err := template.New("home").Parse(`
        <a title={{.Bar | html}}>
    `)
    if err != nil {
        log.Fatalf("could not parse: %v", err)
    }

    foo := Foo{"haha onclick=evil()"}
    if err := tmpl.Execute(os.Stdout, foo); err != nil {
        log.Fatalf("could not execute: %v", err)
    }
}

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.

func main() {
    if len(os.Args) != 2 {
        fmt.Printf("use %s varname\n", os.Args[0])
        os.Exit(1)
    }
    fmt.Println(os.Getenv(os.Args[1]))
}

We can run it as follows:

$ foo=bar getenv foo
bar

os.Exec

What do you expect this code to print?

func main() {
    cmd := exec.Command("getenv", "foo")
    cmd.Env = append(os.Environ(), "foo=newbar")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        log.Fatal(err)
    }
}

bar, or newbar?

another Twitter poll

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

note: values over 1.0 mean tip is faster
note: unofficial benchmark ran on my laptop while playing YouTube videos

More runtime

Garbage Collector

DWARF

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 #17639 made parsing concurrent.

The compiler is faster as a result.

go test

vendor directories are ignored by the go tool #19090:

go test ./...

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

$ go test -test.list .
TestIntegration
TestEmbedStreams
TestEmbedFiles

godoc

You can now link to fields in a struct in the documentation #16753.

Note: This was actually introduced with Go 1.8!

... and much more!

The community

Go meetups

Gophers all around the world! go-meetups.appspot.com

Women Who Go

19 chapters already! www.womenwhogo.org

Women Who Go Gophercon Scholarship

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

Conferences:

Thank you

Francesc Campoy

Google Developer Advocate

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)