Go Course

Melbourne, May-June 2019

Cameron Hutchison

Daniel Cantos

Joshua Carpeggiani

Julia Ogris

Keilin Olsen

Ryan O'Kane

Sai Kiran Gummaraj

Go Gopher

blog.golang.org/gopher
2

Course Overview

Find Slides at go-course.org (source on GitHub)

3

Course Completion

4

Talks

All talks take place at the Charles Goode Auditorium.
Attendance is optional.
The last 30 minutes of each talk are reserved for Q&A and help.

5

Prerequisites

6

Contact

Please join #go-course on anzengineering.slack.com

Instructors
go-instructors@anz.com

@camh, Cameron.Hutchison@anz.com
@Dan, Daniel.Cantos@anz.com
@joshcarp, Joshua.Carpeggiani@anz.com
@julia, Julia.Ogris@anz.com
@keilin, Keilin.Olsen@anz.com
@ryanokane, Ryan.O'Kane@anz.com
@saikirian, SaiKiran.Gummaraj@anz.com

7

History and Overview

8

History of Go

xkcd.com/303/

2007: Robert Griesemer, Rob Pike, and Ken Thompson start working on Go at Google
2008: Russ Cox (go mod) and Ian Taylor (gcc frontend) join
2009: Go goes Open Source
2012: Go version 1.0

9

What is Go?

(Source: Go and the Zen of Python)

10

What does Go look like?

Hello world in Go

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, Melbourne β˜•οΈπŸŽΈπŸˆβ€οΈ")
}

Execute with

language:bash
go run hello.go
11

What is Go NOT?

Go favours simplicity and directness resulting in some purposeful omissions:

12

Why Go

Here is a great read on Rob Pike's blog about "Why Go" - (Less is Exponentially More)

13

Demo

14

Demo

15

Java Spring Boot Initializr

── build.gradle
β”œβ”€β”€ gradle
β”‚Β Β  └── wrapper
β”‚Β Β      β”œβ”€β”€ gradle-wrapper.jar
β”‚Β Β      └── gradle-wrapper.properties
β”œβ”€β”€ gradlew
β”œβ”€β”€ gradlew.bat
β”œβ”€β”€ settings.gradle
└── src
    β”œβ”€β”€ main
    β”‚Β Β  β”œβ”€β”€ java
    β”‚Β Β  β”‚Β Β  └── com
    β”‚Β Β  β”‚Β Β      └── anz
    β”‚Β Β  β”‚Β Β          └── demo
    β”‚Β Β  β”‚Β Β              └── pingserver
    β”‚Β Β  β”‚Β Β                  β”œβ”€β”€ PingserverApplication.java
    β”‚Β Β  β”‚Β Β                  └── controller
    β”‚Β Β  β”‚Β Β                      └── PingController.java        <--------- THAT'S THE ONE
    β”‚Β Β  └── resources
    β”‚Β Β      └── application.properties
    └── test
          .....
                                    └── PingserverApplicationTests.java
16

PingController.java

Source on GitHub

package com.anz.dcx.serverdemo.controller;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PingController {

    @GetMapping(path = "/ping", produces = MediaType.TEXT_PLAIN_VALUE)
    @ResponseBody
    String ping() throws Exception {
        Thread.sleep(2000L);
        return "pong";
    }
}

Execute with

./gradlew clean bootRun
17

Go Implementation

Source on GitHub

language:none
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
└── main.go

Execute with

language:bash
go run main.go
18

Main.go

package main

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

func main() {
    http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(2000 * time.Millisecond)
        fmt.Fprint(w, "pong")
    })
    addr := ":9090"
    fmt.Println("Starting webserver on port", addr)
    log.Fatal(http.ListenAndServe(addr, nil))
}
19

Benchmark

ab -n 19000 -c 19000 -s 200 -r localhost:8080/ping  # Java
ab -n 19000 -c 19000 -s 200 -r localhost:9090/ping  # go
Java median: 102.005 sec
Java 95%:    135.280 sec

Go median:   14.954 sec
Go 95%:      15.061 sec
20

Benchmark

21

Interlude: Towards Continuous Deployment

22

What is Continuous Deployment (CD)?

Continuous Deployment != Continuous Delivery

Yassal Sundman, Continuous Delivery vs Continuous Deployment
23

Continuous Deployment Quotes

"Continuous Deployment is a strategy for software releases wherein any code commit that passes the automated testing phase is automatically released into the production environment."
TechTarget definition

"Continuous deployment requires a highly developed culture of monitoring, being on call, and having the capacity to recover quickly."
Marko Anastasov, Semaphore Engineering Blog

24

Recommendations for CD (1/3)

25

Recommendations for CD (2/3)

Quality leads to the confidence to automatically deploy, so we need
ways to increase and maintain quality.

26

Recommendations for CD (3/3)

27

Protect master branch on GitHub

language:none
Settings -> Options:
[ ] Allow merge commits
[x] Allow squash merging
[ ] Allow rebase merging

Settings -> Branches -> [Add rule|Edit] `master`:
[x] Require pull request reviews before merging
[x] Dismiss stale pull request approvals when new commits are pushed
[x] Require status checks to pass before merging
[x] Require branches to be up to date before merging
[x] Include administrators
28

Commit messages

xkcd.com/1296/
29

Commit messages - spot the difference

chris.beams.io/posts/git-commit/

language:none
$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"

e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing

versus

language:none
$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"

5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage
30

Recipe for great commit messages

chris.beams.io/posts/git-commit/

31

Two git commands for precision work

Don't be afraid!
Try it out on a new, throwaway branch.

32

Rebase interactively

language:none
git log --oneline
58b250e WIP
d558e36 Add coverage and pre-pr checklist to README.md
c9724be Fix copyright holder in LICENCE
aa3b728 Added Apache 2.0 LICENSE
8a2fd40 Initial commit

Drop the latest commit, reword Added... to Add and fold in the Fix... commit with:

language:none
git rebase -i 8a2fd40

and update commits in your editor with:

language:none
reword aa3b728 Added Apache 2.0 LICENSE
fixup  c9724be Fix copyright holder in LICENCE
pick   d558e36 Add coverage and pre-pr checklist to README.md
drop   58b250e WIP
33

Rebase a feature branch

Rebase will sequentially take the commits from feature and reapply them to master:

language:none
         A---B---C feature
        /
   D---E---F---G master

will become

language:none
                 A'--B'--C' feature
                /
   D---E---F---G master

Use the following commands:

language:none
git checkout master
git pull upstream master # or just `git pull` if `master` is set to track `upstream/master`
git checkout feature
git rebase master
git push -f
34

Update branch on Github

For an existing PR you can alternatively click Update branch on Github.
This will merge upstream/master into origin/feature.
Before adding any commits to feature locally run:

language:bash
git pull origin feature
35

Pull Request (PR) recommendations (1/2)

36

Pull Request (PR) recommendations (2/2)

37

Go language fundamentals

38

Tutorials, references and tools

39

Getting started

Notes:
Keep your exported identifiers to as few as possible
Document them

40

Basic types

bool

string

int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr

byte // alias for uint8

rune // alias for int32
     // represents a Unicode code point

float32 float64

complex64 complex128
41

Zero values

language:none
0      for numeric types
false  for the boolean type
""     for strings
nil    for pointers
42

Values and control flow

43

Lab setup

44

Prerequisites

45

Repository setup

language:none
git clone https://github.com/USERNAME/go-course.git
cd go-course
language:bash
git remote add upstream https://github.com/anz-bank/go-course.git
git remote update
git branch -u upstream/master master
git pull
46

PR from own fork - typical git workflow

Start work on a new branch lab1 with:

git checkout master
git pull upstream master  # with upstream/master tracking just use `git pull`
git checkout -b lab1

Write, test and commit code code, then:

git push -u origin
47

Creating PRs

Follow the PR checklist before submitting

When ready, submit and add the Ready for review tag

48

Update feature branch

If master has advanced after feature branch and PR creation you have two options:

Rebase feature branch

language:none
git checkout master
git pull upstream master # or just `git pull` if `master` is set to track `upstream/master`
git checkout feature
git rebase master
git push -f

or

Update branch on GitHub

For an existing PR you can alternatively click Update branch on Github.
This will merge upstream/master into origin/feature.
Before adding any commits to feature locally run:

language:bash
git pull origin feature
49

Lab PR approval flow - Programmer

50

Lab PR approval flow - Reviewer

51

Test samples

Dave Cheney - table driven tests

52

Lab 1 - Fibonacci

func fib(n int)
1
1
2
3
5
8
13
53

Iterable data types and Range

54

Lab 2 - Bubble sort

func bubble(s []int) []int
[1 2 3 5]
55

Lab 3 - Letter frequency

func letters(s string) map[rune]int
func sortLetters(m map[rune]int) []string
a:2
b:1
56

Functions

57

Lab 4 - Numeronym

func numeronyms(vals ...string) []string
[a11y K8s abc]
58

Data structures and interfaces

"The bigger the interface, the weaker the abstraction." - Rob Pike

59

Embedding - Interfaces

"Go does not provide the typical, type-driven notion of subclassing, but it does have the ability to β€œborrow” pieces of an implementation by embedding types within a struct or interface." - Effective Go

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
}
60

Embedding - Structs

"When we embed a type, the methods of that type become methods of the outer type, but when they are invoked the receiver of the method is the inner type, not the outer one." - Effective Go

61

Precedence when Embedding

Embedding types introduces the possiblity for naming conflicts. Go follows some simple rules to help resolve this:

62

Examples

63

Lab 5 - Stringer

127.0.0.1
64

Go for Java devs

65

Go for Java devs

66

Test two implementations of interface in suite (1/2)

// scaler.go
type scaler interface {
    scale(float64)
}

type rect struct {
    a, b int
}

func (r *rect) scale(s float64) {
    r.a = int(float64(r.a) * s)
    r.b = int(float64(r.b) * s)
}

type circle struct {
    r int
}

func (c *circle) scale(s float64) {
    c.r = int(float64(c.r) * s)
}
67

Test two implementations of interface in suite (2/2)

type scalerSuite struct {
    suite.Suite
    scaler scaler
}

func (s *scalerSuite) TestScaler() {
    r := assert.New(s.T())
    initial := fmt.Sprintf("%#v", s.scaler)

    s.scaler.scale(2.0)
    scaled := fmt.Sprintf("%#v", s.scaler)

    s.scaler.scale(0.5)
    scaledBack := fmt.Sprintf("%#v", s.scaler)

    fmt.Printf("%s\n%s\n%s\n", initial, scaled, scaledBack)
    r.Equal(initial, scaledBack)
    r.NotEqual(initial, scaled)
}

func TestStorer(t *testing.T) {
    suite.Run(t, &scalerSuite{scaler: &circle{2}})
    suite.Run(t, &scalerSuite{scaler: &rect{1, 1}})
}
68

Lab 6 - CRUD puppy with interface

J. D. Frazer "Illiad", User Friendly - Crud Puppy
69

Error Handling in Go

70

Errors in Go

type error interface {
    Error() string
}
71

Errors in Go (1/2)

var ErrPermission = errors.New("permission denied")
return fmt.Errorf("archive/tar: missed writing %d bytes", nb)
72

Errors in Go (2/2)

type AddrError struct {
    Err  string
    Addr string
}
func (e *AddrError) Error() string {
    if e == nil {
        return "<nil>"
    }
    s := e.Err
    if e.Addr != "" {
        s = "address " + e.Addr + ": " + s
    }
    return s
}
log.Println(err)
73

Error Handling

"Errors are values." - Rob Pike

74

Defer

defer <function call>
75

Panic and Recover (1/2)

func panic(interface{})
76

Panic and Recover (2/2)

func recover() interface{}
77

Don't Panic

78

Lab 7 - Errors

language:none
- Value < 0
- ID not found in Read, Update and Delete
79

Go Concurrency

80

Topics

81

Concurrency

Definition

Rob Pike (Talk, Slides)

82

Concurrency in Go

Go provides:

83

Goroutines

go <function-call>
84

Channels

ch := make(chan int) // ch is an unbuffered channel of `int` element type
ch := make(chan int, 10) // ch is a buffered channel of size 10 and type `int`
85

Channel Operations (1/2)

ch <- v // send v to the channel ch
v := <-ch // receive from ch and assign it to v
v, ok := <-ch // ok is false if channel is closed and no more data is available
86

Channel Operations (2/2)

for v := range ch {
    fmt.Println(v)
}
87

select Statement

var ch1, ch2 chan int
select {
    case ch1 <- 1:
        fmt.Println("1 sent on ch1")
    case x, ok := <-ch2:
        if ok {
            fmt.Printf("%v received on ch2", x)
        } else {
            fmt.Println("ch2 is closed")
        }
    default:
        fmt.Println("no communication")
}
88

Under the hood: Process, Threads and OS Scheduling

randu.org/tutorials/threads/
89

Under the hood: Go Runtime

Analysis of the Go runtime scheduler
90

Channel Examples

91

Tools and Conventions

92

Project layout

For non-trivial size projects follow the layout suggested by golang-standards
Abridged version:

language:none
β”œβ”€β”€ README.md
β”œβ”€β”€ go.mod
β”œβ”€β”€ go.sum
β”œβ”€β”€ cloudbuild.yaml
β”œβ”€β”€ .gitignore
β”œβ”€β”€ .golangci.yml
β”œβ”€β”€ pkg
β”‚Β Β  β”œβ”€β”€ bar
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ bar.go
β”‚Β Β  β”‚Β Β  β”œβ”€β”€ baz.go
β”‚Β Β  β”‚Β Β  └── bar_test.go
β”‚Β Β  └── foo
β”‚Β Β      β”œβ”€β”€ foo.go
β”‚Β Β      └── foo_test.go
β”œβ”€β”€ cmd
β”‚Β Β  └── fooserver
β”‚Β Β      └── main.go
β”œβ”€β”€ docs
└── vendor
93

Lab 8 - Project Layout

language:none
β”œβ”€β”€ README.md
β”œβ”€β”€ pkg
β”‚Β Β  └── puppy
β”‚Β Β      β”œβ”€β”€ types.go
β”‚Β Β      β”œβ”€β”€ types_test.go
β”‚Β Β      β”œβ”€β”€ errors.go
β”‚Β Β      β”œβ”€β”€ errors_test.go
β”‚Β Β      └── store
β”‚Β Β          β”œβ”€β”€ storer.go
β”‚Β Β          └── .... store files and tests, e.g. mapstore.go
└── cmd
 Β Β  └── puppy-server
 Β Β      └── main.go
94

Go tool chain

language:bash
go help
go version
go build ./...
go test ./...
go install ./...
go mod init
go mod vendor
go mod tidy
go clean -modcache
go test -coverprofile=coverage.out ./... && go tool cover -html=coverage.out
95

Other tools

Lint with

golangci-lint run

and configure the linter in .golangci.yml

Use gofmt or goimport as part of your editor/IDE setup

96

Go standard library

golang.org/pkg/
- fmt
- strings
- time
- encoding/json
- net/http
- regexp
- sort
- database/sql
- os
- path
- bytes
- ...

97

JSON - (De-)Serialisation

func Marshal(v interface{}) ([]byte, error) { /* ... */ }

func Unmarshal(data []byte, v interface{}) error { /* ... */ }
98

JSON - Field Tags

type Car struct {
    Manufacturer string `json:"manufacturer"`
    Model        string `json:"model"`
    Year         int64  `json:"year,omitempty"`
}
99

JSON - Zero Values

100

Examples

101

Lab 9 - JSON puppy

102

Useful third party packages

testify - testing toolkit
chi - lightweight router for Go HTTP services
kingpin.v2 - command line and flag parser
logrus - structured logger

pq - Postgres driver for the database/sql
redigo - lightweight client for Redis
mgo - MongoDB driver for Go
goracle - Oracle driver for the database/sql

jsonschema - JSON schema compilation and validation
go-jose - JWT utils
...

103

A RESTful API starter (1/3)

Full sample code on Go Play Space -
not executable to due 3rd party dependency chi:
basic sample
sample with error handling

type TeapotHandler interface {
    handlePost(w http.ResponseWriter, r *http.Request)
    handleGet(w http.ResponseWriter, r *http.Request)
}

func SetupRoutes(r chi.Router, h TeapotHandler) {
    r.Post("/api/teapot", h.handlePost)
    r.Get("/api/teapot/{id}", h.handleGet)
}

func main() {
    r := chi.NewRouter()
    h := NewMapTeapotHandler()
    SetupRoutes(r, h)
    http.ListenAndServe(":7735", r)
}
104

A RESTful API starter (2/3)

type Teapot struct {
    ID          int
    Colour      string
    Temperature int
}

// MapTeapotHandler implements TeapotHandler
type MapTeapotHandler struct {
    store map[int]Teapot  // Race condition
    maxID int
}

func NewMapTeapotHandler() *MapTeapotHandler {
    return &MapTeapotHandler{store: map[int]Teapot{}}
}
105

A RESTful API starter (3/3)

// MapTeapotHandler implements  TeapotHandler
func (mt *MapTeapotHandler) handleGet(w http.ResponseWriter, r *http.Request) {
    id, _ := strconv.Atoi(chi.URLParam(r, "id"))
    teapot, _ := mt.store[id]
    render.JSON(w, r, teapot)
}

func (mt *MapTeapotHandler) handlePost(w http.ResponseWriter, r *http.Request) {
    var teapot Teapot
    render.DecodeJSON(r.Body, &teapot)
    mt.maxID++ // Race condition
    teapot.ID = mt.maxID
    mt.store[mt.maxID] = teapot
    render.JSON(w, r, teapot)
}
106

Lab 10 - Puppy REST

GET    /api/puppy/{id}
POST   /api/puppy/          Payload: Puppy JSON without ID
PUT    /api/puppy/{id}      Payload: Puppy JSON without ID
DELETE /api/puppy/{id}
map, sync, db
107

Lab 11 - Puppy Notifications

POST   /api/lostpuppy/          Payload: { id: PUPPY_ID }
HTTP status 201 for even IDs
HTTP status 500 for odd IDs
108

Further project work

109

Future of Go

Rob Pike's Talk (Towards Go 2)
Dave Cheney Blog (Past Present and Future of Go)

110

Further Reading

111

References

112

Feedback

Please take a moment to give anonymous feedback at bit.ly/gc-f6k.

Thank you! πŸ™

113

Thank you

Cameron Hutchison

Daniel Cantos

Joshua Carpeggiani

Julia Ogris

Keilin Olsen

Ryan O'Kane

Sai Kiran Gummaraj

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