The State of Go
Where we are in May 2017
Francesc Campoy
Google Developer Advocate
Francesc Campoy
Google Developer Advocate
A recording of this talk is available here.
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.
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.
4Changes since Go 1.8:
Article written by Russ Cox link
In reality, atomically changing all usages of an API is often impossible.
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
9
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
10
Let's move http.Client
to http.Applicant
.
First: create the new API
type Applicant Client
Applicant
has no methods.type Applicant struct { Client }
Applicant
has all the methods of Client
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{}) }
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))
}
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.
// +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) } }
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.
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
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?
21
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")
Garbage Collector
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 {
The compiler has been refactored into multiple packages.
cmd/go/internal/...
Issue #17639 made parsing concurrent.
The compiler is faster as a result.
29
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
You can now link to fields in a struct in the documentation #16753.
tip.golang.org/pkg/net/http/#Client.Transport
Note: This was actually introduced with Go 1.8!
31WWG is sponsoring minority gophers from all over the world to attend Gophercon