History
Created by Google
Robert Griesemer, Rob Pike & Ken Thompson
Open-sourced November 2009
Go 1.0 released March 2012
Slide 4
Slide 4 text
Goals
move away from verbose type systems of java / c++
ease development of multi-threaded applications
easy dependency management & fast compilation
“Do less, enable more”
Slide 5
Slide 5 text
The Language
Designed for concurrent systems programming,
Strongly and statically typed, Compiled, Garbage
collected, Object oriented (ish), Small, opinionated,
and done.
Slide 6
Slide 6 text
Hello World
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, World!")
}
Slide 7
Slide 7 text
Hello World, the HTTP Version
package main
import (
"fmt"
"net/http"
)
func handle(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, World.")
}
func main() {
http.HandleFunc("/", handle)
http.ListenAndServe(":8080", nil)
}
Variable Declaration
var x T // Variable x of type T with a zero value
var x T = v // Variable x of type T with value v
var x = v // Variable x with value v, implicit typing
x := v // Short variable declaration (type inferred)
x, y := v1, v2 // Double declaration (similar with var)
make(T) // make takes a type T, which must be a slice,
// map or channel type, optionally followed by
// a type-specific list of expressions
new(T) // new allocates zeroed storage for a new
// value of type T returns its address
Slide 12
Slide 12 text
Booleans
b1 := true // type is bool
b2 := false
Slide 13
Slide 13 text
Numerics
uint8,16,32,64, int8,16,32,64, float32,64, complex64,128
int + uint (32 or 64 bits, depending on platform)
byte (alias for uint8)
rune (alias for int32)
Strings
s1 := `Raw string literal`
s2 := "Interpreted string literal"
"ᅉ" // UTF-8 input text
`ᅉ` // UTF-8 input text as a raw literal
"\u65e5" // explicit Unicode code points
"\U000065e5" // explicit Unicode code points
"\xe6\x97\xa5" // explicit UTF-8 bytes
Slide 16
Slide 16 text
Runes
'x'
'\n'
'\U00101234'
// range on a string yields runes
for _, r := range "foo" {
fmt.Printf("%s, %T\n", string(r), r)
}
// f, int32
// o, int32
// o, int32
Slide 17
Slide 17 text
Pointers
var p *int // Variable p of type *int (int pointer)
i := 42 // Variable i of type int with value 42
p = &i // Assign the address of i to p
fmt.Println(p) // Output the value of p (the address of i)
fmt.Println(*p) // Output the value of i by using * to
// dereference the pointer p
Blank Identifier
// Discarding a return value when we don't need it
if _, err := os.Stat(path); os.IsNotExist(err) {
fmt.Printf("%s does not exist\n", path)
}
// Importing a library just for side effects
import _ "mylib"
Slide 20
Slide 20 text
Type Conversion
// T(v) converts the value v to type T
i := 42
f := float64(i)
u := uint(f)
Arrays
fixed-length data types
contiguous block of elements of the same type
underlying data structure for both slices and maps
The length of an array is part of its type
Slide 23
Slide 23 text
Arrays
var a1 [10]int // Declare int array with a length of 10
a1[3] = 42 // Write a value to a specific index
i := a[3] // Read a value from a specific index
a2 := [3]int{10, 20, 30} // Declare using an array literal
a3 := [...]int{10, 20, 30} // Declare with a calculated size
a4 := [3]int{1: 10, 2: 20} // Only intialise specific values
a5 := [3]int{} // All positions set to zero-value
l := len(a5) // Built-in len() function reads array size
Slide 24
Slide 24 text
Slices
Abstracts an underlying array
lightweight
reference to array + length + capacity
Slide 25
Slide 25 text
Slices
s1 = make([]int, 5) // Zeroed int slice: len(s1) == 5
s2 = make([]int, 0, 5) // len(s2) == 0, cap(s2) == 5
var s3 []int // Declare a nil slice
s4 := []int{1, 2, 3, 4} // Declare and initialise a slice
s5 := []string{0:"a", 2:"c"} // ["a", "", "c"]
s4 := s2[lo:hi] // Creates a new slice from index lo to hi-1
s5 := s2[1:4] // Slice from index 1 to 3
s6 := s2[:3] // Missing low index implies 0
s7 := s2[3:] // Missing high index implies len(a)
Slide 26
Slide 26 text
Appending to a Slice
func p(x []int) {
fmt.Printf("len=%d cap=%d %v\n", len(x), cap(x), x)
}
var s []int // Define a nil int slice
p(s) // len=0 cap=0 []
s = append(s, 0) // append() works on nil slices
p(s) // len=1 cap=1 [0]
s = append(s, 1) // The slice grows as necessary
p(s) // len=2 cap=2 [0 1]
s = append(s, 2, 3, 4) // append() is variadic
p(s) // len=5 cap=6 [0 1 2 3 4]
Mutating Maps
m := map[string]int{"a": 1, "b": 2}
fmt.Println(m) // map[a:1 b:2]
m["c"] = 3
fmt.Println(m) // map[a:1 b:2 c:3]
delete(m, "b")
fmt.Println(m) // map[a:1 c:3]
if v, ok := m["b"]; !ok {
fmt.Println(v) // 0 (zero value for an int)
}
Slide 29
Slide 29 text
Structs
type Rectangle struct {
Width int
Height int
}
r1 := Rectangle{1, 2} // Create a new Rectangle with w + h
r1.Width = 3 // Set the width to a new value
fmt.Printf("Width = %d; Height = %d\n", r1.Width, r1.Height)
Slide 30
Slide 30 text
Structs
type Rectangle struct {
Width int
Height int
}
var r2 Rectangle // Value is nil
r3 := Rectangle{Height: 1} // w=0 (int zero value), h=1
r4 := Rectangle{} // w=0, h=0
r5 := &Rectangle{1, 2} // Has type *Rectangle
r5.Height = 4 // Dereferencing of struct fields through
// a pointer is transparent
fmt.Println(r2, r3, r4, r5) // {0 0} {0 1} {0 0} &{1 4}
Slide 31
Slide 31 text
Struct Embedding
type Vehicle struct {
speed int
passengers int
}
type Weapon struct {
damage int
}
type Tank struct {
Vehicle
Weapon
}
Marshalling Structs
import (
"encoding/json"
)
type Rectangle struct {
Width int `json:"width"`
Height int `json:"height"`
}
r := Rectangle{3, 4}
j, _ := json.Marshal(r)
fmt.Println(string(j)) // {"width":1,"height":2}
Slide 34
Slide 34 text
Functions
func f1() {} // Simple function definition
func f2(s string, i int) {} // Function that accepts two args
func f3(s1, s2 string) {} // Two args of the same type
func f4(s ...string) {} // Variadic function
func f5() int { // Return type declaration
return 42
}
func f6() (int, string) { // Multiple return values
return 42, "foo"
}
Slide 35
Slide 35 text
Functions
// Named return values act like variables
func f7() (i int, s string) {
i = 42
s = "foo"
return // Naked return returns current values of vars
}
f7 := func() {} // Function as a value
i := 42
func() {
fmt.Println(i) // Function as a closure
}()
Slide 36
Slide 36 text
Functions
All function calls are pass-by-value
Slide 37
Slide 37 text
Functions: defer
func ProcessFile(path string) {
f, _ := os.Open(path)
defer f.Close()
// Do something with the file...
}
Slide 38
Slide 38 text
Functions: defer
func main() {
defer func() {
fmt.Println("One more thing...")
}()
panic("PANIC!")
}
// $ go run scratch.go
// One more thing...
// panic: PANIC!
Slide 39
Slide 39 text
Methods
type Rectangle struct {
Width int
Height int
}
func (r Rectangle) Area() int {
return r.Width * r.Height
}
func main() {
r := Rectangle{Width: 3, Height: 4}
fmt.Println(r.Area()) // Area 12
}
Slide 40
Slide 40 text
Pointer Receivers
Use a pointer receiver if you need to...
1. avoid copying a large data structure
2. mutate the value of the receiver
Interfaces
Provide polymorphism
no implements keyword
interfaces are satisfied implicitly
Slide 43
Slide 43 text
Interfaces
type Speaker interface {
Speak() string
}
type Dog struct { }
func (d Dog) Speak() string { return "Woof" }
type Robot struct { }
func (r Robot) Speak() string { return "Danger!" }
things := []Speaker{Dog{}, Robot{}}
for _, t := range things {
fmt.Println(t.Speak())
}
Slide 44
Slide 44 text
Interface Embedding
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// ReadWriter is the interface that combines the
// Reader and Writer interfaces.
type ReadWriter interface {
Reader
Writer
}
Slide 45
Slide 45 text
All Types are Explicit
int != *int != []int != *[]int != []*int
Slide 46
Slide 46 text
Control Structures
Slide 47
Slide 47 text
If
if x > 0 {
// ...
} else if x < 0 {
// ...
} else {
// ...
}
if err := doWork(); err != nil {
// ...
}
Slide 48
Slide 48 text
For
for x := 0; x < 10; x++ {
// ...
}
x := false
for !x {
// ...
}
for {
// ...
}
Slide 49
Slide 49 text
For
// If looping over an array, slice, string or map,
// or reading from a channel, use a range clause
// to manage the loop:
for index, value := range mySlice {
// ...
}
Slide 50
Slide 50 text
For
for p, c := range “෭ 承" {
fmt.Printf("%#U starts at byte %d\n", c, p)
}
// U+65E5 '෭' starts at byte 0
// U+672C '' starts at byte 3
// U+0020 ' ' starts at byte 6
// U+8A9E '承' starts at byte 7
Slide 51
Slide 51 text
Switch
x := "b"
switch(x) {
case "a":
// ...
case "b":
// ...
default:
// ...
}
switch {
case x == "a":
// ...
fallthrough
case x == "b":
// ...
}
Slide 52
Slide 52 text
Switch
var t interface{}
t = functionReturningSomeType()
switch t := t.(type) {
case string:
// String type value
case int:
// Integer type value
case *bool:
// Boolean pointer type value
default:
// Unhandled type
}
Slide 53
Slide 53 text
Error Handling
type error interface {
Error() string
}
Slide 54
Slide 54 text
Error Handling
func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New("Square root of negative number")
}
// ...
}
f, err := Sqrt(-1)
if err != nil {
fmt.Println(err)
}
Slide 55
Slide 55 text
Concurrency
Slide 56
Slide 56 text
Concurrency
Go has concurrency primitives built in
goroutines for concurrent functions
channels for communicating between goroutines
“Share By Communicating”
Slide 57
Slide 57 text
Goroutines
Lightweight threads of execution
multiplexed across os threads
very cheap to use
Slide 58
Slide 58 text
goroutines
func doWork(i int) {
time.Sleep(time.Millisecond * 500)
fmt.Println(i)
}
func main() {
for i := 1; i <= 5; i++ {
doWork(i)
}
}
Slide 59
Slide 59 text
goroutines
$ time go run g1.go
1
2
3
4
5
go run g1.go ... 2.757 total
Slide 60
Slide 60 text
goroutines
go someFunc() // Concurrency!
Slide 61
Slide 61 text
goroutines
func doWork(i int) {
time.Sleep(time.Millisecond * 500)
fmt.Println(i)
}
func main() {
for i := 1; i <= 5; i++ {
go doWork(i) // concurrency!
}
}
Slide 62
Slide 62 text
goroutines
$ time go run g2.go
go run g2.go ... 0.247 total
Slide 63
Slide 63 text
Goroutines
import "sync"
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
// Do work...
wg.Done()
}()
wg.Wait()
}
Slide 64
Slide 64 text
GOroutines
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go func(x int) {
defer wg.Done()
doWork(x)
}(i)
}
wg.Wait()
}
Slide 65
Slide 65 text
goroutines
$ time go run g3.go
4
1
5
2
3
go run g3.go ... 0.752 total
Slide 66
Slide 66 text
Channels
"Do not communicate by sharing memory;
instead, share memory by communicating."
-- https://golang.org/doc/effective_go.html
Slide 67
Slide 67 text
Channels
ch := make(chan int)
ch <- 42 // Send a value to the channel
v := <-ch // Receive a value from ch
Channels
func doWork(i int, c chan int) {
time.Sleep(time.Millisecond * 500)
c <- i
}
func main() {
c := make(chan int)
for i := 1; i <= 5; i++ {
go doWork(i, c)
}
for i := 1; i <= 5; i++ {
fmt.Println(<-c)
}
}
Slide 75
Slide 75 text
Channels
ch := make(chan int)
close(ch) // Close the channel for writing
v, ok := <-ch // Receive, testing for closure
if !ok {
fmt.Println("Channel closed!")
}
Slide 76
Slide 76 text
Channels
ch := make(chan int)
// Read from channel until it is closed
for i := range ch {
fmt.Println(i)
}
Slide 77
Slide 77 text
Channels
A send to a nil channel blocks forever
A receive on a nil channel blocks forever
A send to a closed channel panics
A receive on a closed channel returns the zero value
Slide 78
Slide 78 text
select
func doWork(c chan int, done chan struct{}) {
select {
case x := <-c:
fmt.Printf("%d received", x)
case <-time.After(time.Second * 1):
fmt.Println("Timeout")
case <-done
return
}
}
Slide 79
Slide 79 text
Mutexs
var counter = struct{
sync.RWMutex
m map[string]int
}{m: make(map[string]int)}
counter.RLock() // Read lock
n := counter.m["some_key"]
counter.RUnlock()
fmt.Println("some_key:", n)
counter.Lock() // Write lock
counter.m["some_key"]++
counter.Unlock()
Slide 80
Slide 80 text
sync/atomic
var ops uint64
for i := 0; i < 50; i++ {
go func() {
for {
atomic.AddUint64(&ops, 1)
runtime.Gosched()
}
}()
}
time.Sleep(time.Second)
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
Slide 81
Slide 81 text
Code Organisation
Slide 82
Slide 82 text
Packaging
all Go programs are organised into packages
all .go files must declare their package
packages must be contained in a single directory
names should be short, concise and lower-case
Slide 83
Slide 83 text
Package Main
Package main denotes that a binary should be built
all executables must have a package main
function main() must also exist for binary to be built
Slide 84
Slide 84 text
Imports
import (
"fmt" // Package from stdlib
"net/http" // Package from stdlib
myfmt "mylib/fmt" // Specifying a custom identifier
// Import remote stringutil package
"github.com/golang/example/stringutil"
// Remote package with blank identifier
_ "github.com/go-sql-driver/mysql"
)
Slide 85
Slide 85 text
Exporting Identifiers
No concept of public / package / private
identifiers are either exported from a package, or not
identifiers starting with a capital are exported
Slide 86
Slide 86 text
Exporting Identifiers
package mylib
type Foo string // Exported, accessible outside the package
type bar string // Only accessible within the mylib package
func NewBar(s string) bar {
return bar(s)
}
Slide 87
Slide 87 text
Exporting Identifiers
package main
import "mylib"
func main() {
// This is fine, because Foo is exported from mylib
s1 := mylib.Foo("a")
// Compile error: "cannot refer to unexported name"
s2 := mylib.bar("b")
// We can still get a bar value through this function
s3 := mylib.NewBar("c")
}
Slide 88
Slide 88 text
Workspaces
a workspace is a directory hierarchy
must contain src, pkg & bin directories in the root
$GoPATH gives the location of your workspace
Keep all go code in one workspace
Tooling
go build: compile packages & dependencies
go run: compile & run an application
go test: run your test cases
go get: download and install packages
Godoc: Display & Generate package documentation
Slide 92
Slide 92 text
Tooling
gofmt: format your code in the only acceptable way
goimports: go fmt + import management
golint: checks code for style violations
go vet: find common coding errors
oracle: source analysis tool
Slide 93
Slide 93 text
and finally...
Slide 94
Slide 94 text
Find out more
https://golang.org/ref/spec
https://tour.golang.org/
https://golang.org/doc/code.html
https://golang.org/doc/effective_go.html