Go (January 12, 2010)

# 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:

- verbose, lots of repetition
- too much focus on type hierarchy
- types get in the way as much as they help
- compiles take far too long

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

- errors at run time that should be caught statically
- no compilation means slow code

## 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):

- C: `#include <stdio.h>` reads 360 lines from 9 files.
- C++: `#include <iostream>` reads 25,326 lines from 131 files.
- Objective C: `#include <Carbon/Carbon.h>` reads 124,730 lines from 689 files.

## 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?