Introduction to Go

School of Computing Science, Glasgow University

13 October 2014

Dave Cheney

Licence and attribution

This talk is an amalgam of a talk I gave to the Canberra Go users group

and Robert Griesemer's "A Taste of Go"

From which I borrowed much of the "Program elements" section as Robert's description of the language was much better than my attempt.

As this talk is a derivative, it continues to be licenced under the BSD licence that covers the Go project.

2

The Go programming language

Designed by programmers for programmers!

3

Origins of Go

Go started in 2007 by Rob Pike, Robert Griesemer, Ken Thompson.

Russ Cox and Ian Lance Taylor joined soon after.

There is a story that Go was designed while waiting for a C++ program to compile.

In reality, Go was a response to the many of the frustrations that Rob, Robert and Ken experienced with the languages in use at Google at that time; C++, Java, and Python.

Rob Pike's 2012 paper, Less is exponentially more gives an excellent overview of the environment that gave rise to Go.

4

Public announcement

First public announcement November 10th, 2009. The Go Programming Language, 2009

Go is an open source project.

All the commits, code review, design, debate, etc, are all done in the open on a public mailing lists.

5

2009 - 2012

Rapid iteration over the next 2.5 years

Go 1.0 was released on the 28th of March, 2012.

Go 1.0 marked a line in the sand

Stability

6

2012 - now

3 point releases so far; Go 1.1, 1.2, and 1.3.

The fourth, Go 1.4, is on target to ship in December.

Rough 6 month release cycle; 3 month change window, 3 month stabilisation.

Big ticket features are discussed before the change window opens.

Each release has bought incremental improvements in the compilers, the runtime, the garbage collector.

New platforms and new architectures added.

7

Hello, World!

package main

import "fmt"

func main() {
    fmt.Println("Hello, 世界!")
}
8

Hello, World! Internet-style

package main

import (
    "fmt"
    "log"
    "net/http"
)

func HelloServer(w http.ResponseWriter, req *http.Request) {
    log.Println(req.URL)
    fmt.Fprintf(w, "Hello, 世界!\nURL = %s\n", req.URL)
}

func main() {
    fmt.Println("please connect to localhost:7777/hello")
    http.HandleFunc("/hello", HelloServer)
    log.Fatal(http.ListenAndServe(":7777", nil))
}
9

Program elements

10

Constants

const e = 2.71828182845904523536028747135266249775724709369995957496696763
const third = 1/3
const M64 int64 = 1<<20
const M = 1<<20
const big = 1<<100 / 1e30  // valid constant expression

Compiler complains if a constant doesn't fit where it is used.

11

Variables

var x int
var s, t string
var x int
var s, t string = "foo", "bar"  // multiple assignment

var x = 42                      // int
var s, b = "foo", true          // string, bool
x := 42
s, b := "foo", true
return &x
12

Types

uint8 (byte), uint16, uint32, uint32, uint64,
int8, int16, int32, int32 (rune), int64,
float32, float64,
complex64, complex128,
uint, int, uintptr,
bool, string,
error  // not so usual
array, struct, pointer, function,
slice, map, channel
interface
13

Type declarations

[10]byte  // array of 10 bytes

struct {
    name        string
    left, right *Node
    action      func(*Node)
}

func(a, b, c int)
func(http.ResponseWriter, *http.Request) error
type Weekday int

type Point struct {
    x, y int
}
14

Slices

[]T  // slice of T

Common slice operations:

len(s)
s[i]
s[i:j]
append(s, x)  // append element x to slice s and return new slice
15

Pointers

x := 1000
y := &x
y += 4          // nope
16

Maps

map[K]V  // map K -> V

Common map operations:

make(map[K]V)
len(m)
m[k]
delete(m, k)
for key, value := range m {
    // order of key sequence different each time
}
17

Statements

a, b = b, a                 // swap
f, err = os.Open(filename)

if x < y {
    return x
} else {
    return y
}

switch day {
case Mon:
    ...
    // break is implicit
case Tue, Wed:
    ...
}
18

Statements, continued

for {
    // loop forever
}

range over arrays, slices, and maps

for i, num := range numbers { ... }
for city, pop := range population { ... }

Not shown: break, goto, continue, fallthrough

19

Functions

func Sin(x float64) float64
func AddScale(x, y int, f float64) int
func Write(data []byte) (written int, err error)
func Printf(format string, args ...interface{})
var delta int
return func(x int) int { return x + delta }
20

Methods

Methods are functions with a receiver parameter:

func (p Point) String() string {
    return fmt.Sprintf("(%d, %d)", p.x, p.y)
}

The receiver binds the method to its base type (Point):

type Point struct {
    x, y int
}

Methods are invoked via the usual dot notation:

// +build OMIT

package main

import "fmt"

// Point START OMIT
type Point struct {
	x, y int
}

// Point END OMIT

// String START OMIT
func (p Point) String() string {
	return fmt.Sprintf("(%d, %d)", p.x, p.y)
}

// String END OMIT

func main() {
    p := Point{2, 3}
    fmt.Println(p.String())
    fmt.Println(Point{3, 5}.String())
}
21

Methods can be defined for any user-defined type!

For the Weekday type:

type Weekday int

Define String method on Weekday:

func (d Weekday) String() string { // ...
// +build OMIT

package main

import "fmt"

// type START OMIT
type Weekday int

// type END OMIT

const (
	Mon Weekday = iota
	Tue
	Wed
	Thu
	Fri
	Sat
	Sun
)

var names = [...]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}

// String START OMIT
func (d Weekday) String() string { // ...
	// String END OMIT
	return names[d]
}

func main() {
    fmt.Println(Mon.String())
    fmt.Println()

    for d := Mon; d <= Sun; d++ {
        fmt.Println(d.String())
    }
}

Method calls via non-interface types are statically dispatched.

22

Interface types

Examples:

interface{}  // empty interface

interface {
    String() string
}

interface {
    Len() int
    Swap(i, j int)
    Less(i, j int) bool
}
23

Using interfaces

type Stringer interface {
    String() string
}

Both Weekday and Point define a String method, so values of both can be assigned to
a variable of Stringer type:

// +build OMIT

package main

import "fmt"

type Point struct {
	x, y int
}

func (p Point) String() string {
	return fmt.Sprintf("(%d, %d)", p.x, p.y)
}

type Weekday int

const (
	Mon Weekday = iota
	Tue
	Wed
	Thu
	Fri
	Sat
	Sun
)

var names = [...]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}

func (d Weekday) String() string { // ...
	return names[d]
}

// Stringer START OMIT
type Stringer interface {
	String() string
}

// Stringer END OMIT

func main() {
    var x Stringer
    x = Point{2, 3}
    fmt.Println("A", x.String())

    x = Tue
    fmt.Println("B", x.String())

    fmt.Println("C", Point{2, 3}) // fmt.Println knows about Stringer!
    fmt.Println("D", Tue)
}

Method calls via interface types are dynamically dispatched ("virtual function call").

24

Concurrency

25

Goroutines

go f()
go f(x, y, ...)
26

A simple example

func f(msg string, delay time.Duration) {
    for {
        fmt.Println(msg)
        time.Sleep(delay)
    }
}

Function f is launched as 3 different goroutines, all running concurrently:

// +build OMIT

package main

import (
	"fmt"
	"time"
)

// f START OMIT
func f(msg string, delay time.Duration) {
	for {
		fmt.Println(msg)
		time.Sleep(delay)
	}
}

// f END OMIT

func main() {
    go f("A--", 300*time.Millisecond)
    go f("-B-", 500*time.Millisecond)
    go f("--C", 1100*time.Millisecond)
    time.Sleep(20 * time.Second)
}
27

Communication via channels

A channel type specifies a channel value type (and possibly a communication direction):

chan int
chan<- string  // send-only channel
<-chan T       // receive-only channel

A channel is a variable of channel type:

var ch chan int
ch := make(chan int)  // declare and initialize with newly made channel

A channel permits sending and receiving values:

ch <- 1   // send value 1 on channel ch
x = <-ch  // receive a value from channel ch (and assign to x)

Channel operations synchronize the communicating goroutines.

28

Communicating goroutines

Each goroutine sends its results via channel ch:

func f(msg string, delay time.Duration, ch chan string) {
    for {
        ch <- msg
        time.Sleep(delay)
    }
}

The main goroutine receives (and prints) all results from the same channel:

// +build OMIT

package main

import (
	"fmt"
	"time"
)

// f START OMIT
func f(msg string, delay time.Duration, ch chan string) {
	for {
		ch <- msg
		time.Sleep(delay)
	}
}

// f END OMIT

func main() {
    ch := make(chan string)
    go f("A--", 300*time.Millisecond, ch)
    go f("-B-", 500*time.Millisecond, ch)
    go f("--C", 1100*time.Millisecond, ch)

    for i := 0; i < 100; i++ {
        fmt.Println(i, <-ch)
    }
}
29

Packages

Packages you import are referenced by their package's prefix.

import "fmt"

func main() {
    fmt.Printf("Hello %s\n", "world)
}

Import cycles are not permitted.

30

Language implementation

31

Small, well polished standard library

To a first order approximation, the std lib provides only the things needed to build Go itself.

32

Excellent cross platform support

Cross platform is defined as the super set of all platforms with some not supporting a particular feature, rather than the lowest common denominator.

Two production compiler implementations

Other implementations, llgo, tardis-go, etc, keep us honest by writing to the spec.

33

Tools

/usr/bin/go

Simple, zero configuration, build tool.

All commands and paths are relative to your $GOPATH workspace.

Supports conditional compilation via suffixes and build tags.

Support for cross compilation.

GOARCH=386 GOOS=windows go build mycmd
34

More tools

Read package documentation

godoc $PKG

Lint your code

go vet $PKG

Solve code formatting issues, once and for all

go fmt $PKG

Built in testing framework, including benchmarking and coverage reports

go test $PKG
go test -cover $PKG

Built in race detector (based on ThreadSantizer)

go {build,test,install} -race $PKG
35

How to get started

Start with the tour, tour.golang.org

Read Effective Go

Online communities

36

Questions

This talk is online

talks.godoc.org/github.com/davecheney/presentations/introduction-to-go.slide

All the links inside the talk are clickable, I encourage you to follow them.

Also, please take the time to visit

37

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