The Go Programming Language

Russ Cox


Stanford University

January 12, 2010

Go

New

Experimental

Concurrent

Garbage-collected

Systems

Language

Hello, world

package main

import "fmt"

func main() {
	fmt.Printf("Hello, 世界\n")
}

History

Design started in late 2007.

Implementation starting to work mid-2008.

Released as an open source project in November 2009.

Work continues.

Robert Griesemer, Ken Thompson, Rob Pike, Ian Lance Taylor, Russ Cox, many others

Why?

Go fast!

Make programming fun again.

Why isn't programming fun?

Compiled, statically-typed languages (C, C++, Java) require too much typing and too much typing:

Dynamic languages (Python, JavaScript) fix these problems (no more types, no more compiler) but introduce others:

Can we combine the best of both?

Go

Make the language fast.

Make the tools fast.

Go Approach: Static Types

Static types, but declarations can infer type from expression:

var one, hi = 1, "hello"

var double = func(x int) int { return x*2 }

Not full Hindley-Milner type inference.

Go Approach: Methods

Methods can be defined on any type.

type Point struct {
	X, Y float64
}

func (p Point) Abs() float64 {
	return math.Sqrt(p.X*p.X + p.Y*p.Y)
}

Go Approach: Methods

Methods can be defined on any type.

type MyFloat float64

func (f MyFloat) Abs() float64 {
	v := float64(f)
	if v < 0 {
		v = -v
	}
	return v
}

Go Approach: Abstract Types

An interface type lists a set of methods. Any value with those methods satisfies the interface.

type Abser interface {
	Abs() float64
}

func AbsPrinter(a Abser)

Can use Point or MyFloat (or ...):

p := Point{3, 4}
AbsPrinter(p)

f := MyFloat(-10)
AbsPrinter(f)

Notice that Point never declared that it implements Abser. It just does. Same with MyFloat.

Go Approach: Packages

A Go program comprises one or more packages.

Each package is one or more source files compiled and imported as a unit.

package draw

type Point struct {
	X, Y int
}
package main

import "draw"

var p draw.Point

Go Approach: Visibility

Inside a package, all locally defined names are visible in all source files.

When imported, only the upper case names are visible.

package draw

type Point struct {
	X, Y int
	dist float64
}

type cache map[Point] float64

Clients that import "draw" can use the black names only.

“Shift is the new public.”

Go Approach: Concurrency

Cheap to create a new flow of control (goroutine):

func main() {
	go expensiveComputation(x, y, z)
	anotherExpensiveComputation(a, b, c)
}

Two expensive computations in parallel.

Go Approach: Synchronization

Use explicit messages to communicate and synchronize.

func computeAndSend(ch chan int, x, y, z int) {
	ch <- expensiveComputation(x, y, z)
}

func main() {
	ch := make(chan int)
	go computeAndSend(ch, x, y, z)
	v2 := anotherExpensiveComputation(a, b, c)
	v1 := <-ch
	fmt.Println(v1, v2)
}

Notice communication of result in addition to synchronization.

Go Fast: Language

Static types: enough to compile well, but inferred much of the time.

Methods: on any type, orthogonal to type system.

Abstract types: interface values, relations inferred statically.

Visibility: inferred from case of name.

Concurrency: lightweight way to start new thread of control.

Synchronization: explicit, easy message passing.


Lightweight feel of a scripting language but compiled.

Compile fast

Observation: much of the compile time for a source file is spent processing other, often unrelated files.

In C: a.c includes b.h, which includes c.h, which includes d.h.

Except that it's more often a tree instead of a chain.

On my Mac (OS X 10.5.8, gcc 4.0.1):

And we haven't done any real work yet!

Same story in Java, Python, but reading binaries instead of source files.

Implementation: Summarize Dependencies

package gui

import "draw"

type Mouse struct {
	Loc draw.Point
	Buttons uint
}

Compiled form of gui summarizes the necessary part of draw (just Point).

Implementation: Summarize Dependencies

Compiled form of gui summarizes the necessary part of draw (just Point). Pseudo-object:

package gui
type draw.Point struct {
	X, Y int
}
type gui.Mouse struct {
	Loc draw.Point
	Buttons uint
}

A file that imports gui compiles without consulting draw or its dependencies.

In Go: import "fmt" reads one file: 184 lines summarizing types from 7 packages.

Tiny effect in this program but can be exponential in large programs.

Compilation Demo

Build all standard Go packages: ~120,000 lines of code.

Go Status

Open source:

  • released on November 10, 2009
  • regular releases (~ weekly)
  • all development done in public Mercurial repository
  • outside contributions welcome

Portable:

  • FreeBSD, Linux, OS X (x86, x86-64)
  • (in progress) Linux arm, Native Client x86, Windows x86.

Still in progress, experimental. Yet to come:

  • mature garbage collector
  • generics?
  • exceptions?
  • unions or sum types?

Questions?