What's new in Go 1.1

Andrew Gerrand

Gopher

Go 1.1

Not finished yet. Monday maybe?

2

Language changes

3

Integer division by zero

Integer division by constant zero is now a compile-time error:

// +build ignore,OMIT

package main

func f(x int) int {
    return x / 0
}

func main() {
	f(1)
}
4

Unicode

Byte order marks are now permitted as the first character of a Go source file.

The misuse of "surrogate halves" is now caught by the compiler, libraries, and run-time.

If you don't know what this means, then it likely doesn't matter to you.

5

Method values

Sometimes you want to turn a method into a plain function (binding it to its receiver). This is often referred to as "currying".

To do this under Go 1.0, you would use a closure:

// +build ignore,OMIT

package main

import "os"

func main() {
    var w func([]byte) (int, error)
    w = func(b []byte) (int, error) { return os.Stdout.Write(b) }
    w([]byte("hello!\n"))
}

Go 1.1 now implements method values, so you can achieve the same thing by simply taking the method as a value:

// +build ignore,OMIT

package main

import "os"

func main() {
    var w func([]byte) (int, error)
    w = os.Stdout.Write
    w([]byte("hello!\n"))
}
6

Return requirements (1/2)

Before Go 1.1, a function that returned a value needed an explicit return or call to panic at the end of the function.

func slurp(r io.Reader) error {
    b := make([]byte, 1024)
    for {
        _, err := r.Read(b)
        if err != nil {
            if err == io.EOF {
                return nil
            }
            return err
        }
    }
    panic("unreachable")
}
func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}
7

Return requirements (2/2)

In Go 1.1, the rule about final "return" statements is more permissive.

func slurp(r io.Reader) error {
    b := make([]byte, 1024)
    for {
        _, err := r.Read(b)
        if err != nil {
            if err == io.EOF {
                return nil
            }
            return err
        }
    }
}
func min(a, b int) int {
    if a < b {
        return a
    } else {
        return b
    }
}
8

Implementation and tools

9

Size of int on 64-bit architectures

Under Go 1.0, int and uint were 32 bits wide on all systems.

With Go 1.1, both the gc and gccgo implementations now make int and uint 64 bits on 64-bit platforms such as AMD64/x86-64.

Among other things, this enables the allocation of slices with more than 2 billion elements on 64-bit platforms.

10

Heap size on 64-bit architectures

On 64-bit architectures, the maximum heap size has been enlarged substantially, from a few gigabytes to several tens of gigabytes. (The exact details depend on the system and may change.)

On 32-bit architectures, the heap size has not changed.

11

Race detector

A major addition to the tools is a race detector, a way to find bugs in concurrent programs. To enable it, set the -race flag when building or testing your program.

package main

func main() {
    var a int
    go func() {
        for {
            if a == 0 {
                a = 1
            }
        }
    }()
    for {
        if a == 1 {
            a = 0
        }
    }
}

For now, it is only available on 64-bit Linux, OS X, and Windows systems.

12

The go command

The go command now gives better error messages:

$ go build foo/quxx
can't load package: package foo/quxx: cannot find package "foo/quxx" in any of:
    /home/you/go/src/pkg/foo/quxx (from $GOROOT)
    /home/you/src/foo/quxx (from $GOPATH)

To help users better understand workspaces and GOPATH, the go get command will fail if GOPATH is not set:

$ GOPATH= go get code.google.com/p/foo/quxx
package code.google.com/p/foo/quxx: cannot download, $GOPATH not set.
For more details see: go help gopath

The go get command will also fail if GOPATH and GOROOT have the same value:

$ GOPATH=$GOROOT go get code.google.com/p/foo/quxx
warning: GOPATH set to GOROOT (/home/you/go) has no effect
package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT.
For more details see: go help gopath
13

The go test command (1/2)

The go test command no longer deletes the binary when run with profiling enabled, to make it easier to analyze the profile. After running

$ go test -cpuprofile cpuprof.out mypackage

the file mypackage.test will be left around for analysis.

14

The go test command (2/2)

The go test command can now generate profiling information that reports where goroutines are blocked, enabled with the -blockprofile option. The information is presented as a blocking profile.

15

Build constraints

The "go1.1" tag has been added to the list of default build constraints.

To build a file only with Go 1.1 and above, add this build constraint:

// +build go1.1

To build a file only with Go 1.0.x, use the converse constraint:

// +build !go1.1

This permits packages to take advantage of the new features in Go 1.1 while remaining compatible with earlier versions of Go.

16

Additional platforms

The Go 1.1 tool chain adds experimental support for freebsd/arm, netbsd/386, netbsd/amd64, netbsd/arm, openbsd/386 and openbsd/amd64 platforms.

An ARMv6 or later processor is required for freebsd/arm or netbsd/arm.

Go 1.1 adds experimental support for cgo on linux/arm.

17

Standard library

18

bufio.Scanner (1/2)

The old way:

    r := bufio.NewReader(strings.NewReader(blob))
    for {
        s, err := r.ReadString('\n')
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Fatal(err)
        }
        fmt.Println(s)
    }

The new way:

// +build ignore,OMIT

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"strings"
)

const blob = `Hey there,
fellow gophers!
Have a good day.
`

func old() {
	// STARTold OMIT
	r := bufio.NewReader(strings.NewReader(blob))
	for {
		s, err := r.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			log.Fatal(err)
		}
		fmt.Println(s)
	}
	// STOP OMIT
}

func main() {
    s := bufio.NewScanner(strings.NewReader(blob))
    for s.Scan() {
        fmt.Println(s.Text())
    }
    if err := s.Err(); err != nil {
        log.Fatal(err)
    }
}
19

bufio.Scanner (2/2)

Custom split functions:

type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

For example, counting words:

// +build ignore,OMIT

package main

import (
	"bufio"
	"fmt"
	"log"
	"strings"
)

func main() {
    const input = "Now is the winter of our discontent..."
    scanner := bufio.NewScanner(strings.NewReader(input))
    scanner.Split(bufio.ScanWords)
    count := 0
    for scanner.Scan() {
        count++
    }
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
    fmt.Println(count)
}
20

reflect (1/2)

The new functions ChanOf, MapOf and SliceOf construct new types from existing types, for example to construct the type chan T given only T.

// +build ignore,OMIT

package main

import (
	"fmt"
	"reflect"
)

func sendSlice(slice interface{}) (channel interface{}) {
    sliceValue := reflect.ValueOf(slice)
    chanType := reflect.ChanOf(reflect.BothDir, sliceValue.Type().Elem())
    chanValue := reflect.MakeChan(chanType, 0)
    go func() {
        for i := 0; i < sliceValue.Len(); i++ {
            chanValue.Send(sliceValue.Index(i))
        }
        chanValue.Close()
    }()
    return chanValue.Interface()
}

func main() {
    ch := sendSlice([]int{1, 2, 3, 4, 5}).(chan int)
    for v := range ch {
        fmt.Println(v)
    }
}
21

reflect (2/2)

The new function MakeFunc creates a wrapper function to make it easier to call a function with existing Values.

// +build ignore,OMIT

package main

import (
	"fmt"
	"reflect"
)

func makeSwap(fptr interface{}) {
    swap := func(in []reflect.Value) []reflect.Value {
        return []reflect.Value{in[1], in[0]}
    }
    fn := reflect.ValueOf(fptr).Elem()
    v := reflect.MakeFunc(fn.Type(), swap)
    fn.Set(v)
}

func main() {
    var fn func(int, int) (int, int)
    makeSwap(&fn)
    fmt.Println(fn(0, 1))
}
22

time (1/4)

On FreeBSD, Linux, NetBSD, OS X and OpenBSD, previous versions of the time package returned times with microsecond precision. Go 1.1 now provides nanosecond precision on these systems.

23

time (2/4)

The new method on time.Time, YearDay, provides the one-indexed day number of the year.

// +build ignore,OMIT

package main

import (
	"fmt"
	"time"
)

func main() {
    fmt.Println("Today is day", time.Now().YearDay())
}
24

time (3/4)

The Timer type has a new method Reset that modifies the timer to expire after a specified duration. This helps to avoid unnecessary repeated Timer allocations.

// +build ignore,OMIT

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func init() {
	rand.Seed(10)
}

func sendMessages() chan string {
	ch := make(chan string)
	go func() {
		for i := 0; ; i++ {
			time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
			ch <- fmt.Sprintf("message %v", i)
		}
	}()
	return ch
}

func main() {
    timeout := time.NewTimer(80 * time.Millisecond)
    ch := sendMessages()
    for {
        select {
        case msg := <-ch:
            fmt.Println(msg)
            timeout.Reset(80 * time.Millisecond)
        case <-timeout.C:
            fmt.Println("timeout")
            return
        }
    }
}
25

time (4/4)

The new function ParseInLocation parses the time in the context of a time zone, ignoring time zone information in the parsed string.

This function addresses a common source of confusion in the time API.

26

bytes and strings

TrimPrefix and TrimSuffix functions have been added to the bytes and strings packages.

Code under Go 1.0 like this:

s := "Please pass the salt"
if p := "Please "; strings.HasPrefix(s, p) {
    s = s[len(p):]
}

May now be rewritten as:

s := "Please pass the salt"
s = strings.TrimPrefix(s, "Please ")
27

Exp and old subtrees moved

The exp and old source subtrees, which are not included in binary distributions, have been moved to the new go.exp sub-repository at golang.org/x/exp.

To access the ssa package, for example, run

$ go get golang.org/x/exp/ssa

and then in Go source,

import "golang.org/x/exp/ssa"

The old package exp/norm has also been moved, but to a new repository go.text, where the Unicode APIs and other text-related packages will be developed.

28

Performance

29

Performance

Code compiled with the Go 1.1 gc tool suite should be noticeably better for most Go programs.

Improvements relative to Go 1.0 seem to be about 30%-40%, sometimes much more, but occasionally less or even non-existent.

Major changes include:

30

Thank you

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.)