Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Gophers! Go, google's open source language - WXG Guildford 2013

Ben Lovell
October 25, 2013

Gophers! Go, google's open source language - WXG Guildford 2013

Go was conceived within Google to scratch their itch for a fully featured systems programming language with a super-fast compiler and runtime performance close to that of the C programming language.

We'll take a high level glance at how Go can help you write performant and maintainable servers and applications, how Go's language-level concurrency constructs "go-routines" and "channels" make traditional multithreading headaches a thing of the past and a brief look into Go's "batteries included" amazing standard library.

Go is built from the ground up for concurrency - a commonly misunderstood term and often used interchangeably with parallelism. We'll talk about this distinction and why it is increasingly significant in the age of multicore and multi-CPU systems and servers.

Of course, Go isn't perfect. I'll take you on a tour of some of Go's controversial design decisions and the reasoning behind them. Hopefully turning the typical and initial reaction - "huh?" into "ah!"

This talk was presented at WXG Guildford. http://wxg.co.uk

Ben Lovell

October 25, 2013
Tweet

More Decks by Ben Lovell

Other Decks in Programming

Transcript

  1. gophers!
    Ben Lovell

    View Slide

  2. benlovell
    _j

    View Slide

  3. 113581334398839860922
    (thanks, google)

    View Slide

  4. View Slide

  5. View Slide

  6. sometimes we don’t get along…

    View Slide

  7. View Slide

  8. View Slide

  9. what is go?
    … and why does it exist

    View Slide

  10. go will be the server
    language of the future
    - Tobias Lütke, Shopify founder

    View Slide

  11. go is fast

    View Slide

  12. go is object-oriented
    (but not as you know it)

    View Slide

  13. go is statically typed

    View Slide

  14. go is garbage collected

    View Slide

  15. go is concurrent

    View Slide

  16. optimised for
    developer happiness

    View Slide

  17. a brief history of go

    View Slide

  18. started in 2007
    by three googlers…

    View Slide

  19. Rob Pike

    View Slide

  20. Ken Thompson

    View Slide

  21. Robert Griesemer

    View Slide

  22. open sourced in 2009
    (over 300 contributors to date)

    View Slide

  23. 1.0 release
    March 2012

    View Slide

  24. what was left out is
    more important than
    what was put in
    - UNIX philosophy

    View Slide

  25. hello, world!

    View Slide

  26. package main
    !
    import "fmt"
    !
    func main() {
    fmt.Println("Hello, world!")
    }

    View Slide

  27. the type system

    View Slide

  28. package main
    !
    import "fmt"
    !
    type Person string
    !
    func (person Person) Greet() {
    fmt.Printf("Hello, %s!\n", person)
    }
    !
    func main() {
    person := Person("Ben")
    person.Greet()
    }
    !

    View Slide

  29. package main
    !
    import "fmt"
    !
    type Person struct {
    Name string
    Age int
    }
    !
    func (person Person) Greet() {
    fmt.Println(person.Name)
    }
    !
    func main() {
    person := Person{"Ben", 33}
    person.Greet()
    }
    !

    View Slide

  30. no classes…

    View Slide

  31. …no type hierarchy

    View Slide

  32. favour composition
    over inheritance

    View Slide

  33. arranging code
    in packages

    View Slide

  34. % export GOPATH=/gocode/
    !
    /gocode
    /gocode/src

    View Slide

  35. package person
    !
    import "fmt"
    !
    type Person struct {
    Name string
    }
    !
    func (person Person) Greet() string {
    return fmt.Sprintf("Hello, %s", person.Name)
    }
    ~/gocode/src/person/person.go

    View Slide

  36. ~/gocode/src/main.go
    ~/gocode/src % go run main.go
    package main
    !
    import (
    "fmt"
    "person"
    )
    !
    func main() {
    person := person.Person{"Ben"}
    greeting := person.Greet()
    fmt.Println(greeting)
    }
    !

    View Slide

  37. visibility?

    View Slide

  38. start your identifier
    with a lowercase letter
    to make it private

    View Slide

  39. function arguments
    are copied

    View Slide

  40. package main
    !
    import (
    "fmt"
    "strings"
    )
    !
    func Upcase(name string) {
    name = strings.ToUpper(name)
    }
    !
    func main() {
    name := "ben"
    Upcase(name)
    !
    fmt.Println(name)
    }
    !
    // ben

    View Slide

  41. pointers!
    (scream)

    View Slide

  42. // BEN
    package main
    !
    import (
    "fmt"
    "strings"
    )
    !
    func Upcase(name *string) {
    *name = strings.ToUpper(*name)
    }
    !
    func main() {
    name := "ben"
    Upcase(&name)
    !
    fmt.Println(name)
    }
    !

    View Slide

  43. the same applies to
    function receivers

    View Slide

  44. package main
    !
    import "fmt"
    !
    type Person struct {
    Name string
    }
    !
    func (p Person) SetName(name string) {
    p.Name = name
    }
    !
    func main() {
    p := Person{"Ben"}
    p.SetName("Jim")
    fmt.Println(p.Name)
    }
    !
    // Ben

    View Slide

  45. // Jim
    package main
    !
    import "fmt"
    !
    type Person struct {
    Name string
    }
    !
    func (p *Person) SetName(name string) {
    p.Name = name
    }
    !
    func main() {
    p := Person{"Ben"}
    p.SetName("Jim")
    fmt.Println(p.Name)
    }
    !

    View Slide

  46. pointers are not just for
    reference semantics

    View Slide

  47. pointers are not just for
    reference semantics
    Christmas

    View Slide

  48. representing is-a
    with type embedding
    (well, kinda)

    View Slide

  49. // I’M BEN
    // I’m Ben
    type Person struct {
    Name string
    }
    !
    func (p Person) Greet() {
    fmt.Println("I'm", p.Name)
    }
    !
    type Manager struct {
    Person
    }
    !
    func (m Manager) Greet() {
    fmt.Println("I'M", strings.ToUpper(m.Name))
    }
    !
    func main() {
    m := Manager{Person{"Ben"}}
    m.Greet()
    m.Person.Greet()
    }

    View Slide

  50. signature based
    polymorphism
    (quack quack)

    View Slide

  51. View Slide

  52. interfaces

    View Slide

  53. type Person struct {
    Name string
    }
    !
    func (p Person) Greet() {
    fmt.Println("I'm", p.Name)
    }
    !
    type Manager struct {
    Person
    }
    !
    func (m Manager) Greet() {
    fmt.Println("I'M", strings.ToUpper(m.Name))
    }
    !
    func greet(greeters ...Greeter) {
    for _, g := range greeters {
    g.Greet()
    }
    }
    !
    type Greeter interface {
    Greet()
    }
    !
    func main() {
    greet(Person{"Ben"}, Manager{Person{"Bob"}}, Person{"Anne"})
    }

    View Slide

  54. interfaces are
    implicitly satisfied

    View Slide

  55. querying for support
    and casting

    View Slide

  56. func greet(greeters ...interface{}) {
    for _, g := range greeters {
    g.(Greeter).Greet()
    }
    }

    View Slide

  57. don’t.
    there are safe idioms

    View Slide

  58. func greet(greeters ...interface{}) {
    for _, g := range greeters {
    greetable, ok := g.(Greeter)
    if ok {
    greetable.Greet()
    } else {
    fmt.Println("Whoops!")
    }
    }
    }
    !
    func main() {
    greet(Person{"Ben"}, "WHOA!", Person{"Anne"})
    }
    !
    // I’m Ben
    // Whoops!
    // I’m Anne

    View Slide

  59. error handling
    (the error interface!)

    View Slide

  60. type error interface {
    Error() string
    }

    View Slide

  61. // os.Open signature
    func Open(name string) (file *File, err error)
    !
    !
    f, err := os.Open("file.txt")
    if err != nil {
    log.Fatal(err)
    }
    // do something with the open file

    View Slide

  62. f, err := os.Open("file.txt")
    if err != nil {
    log.Fatal(err)
    }
    !
    defer f.Close()
    // do something with the *File f

    View Slide

  63. concurrency
    (kind hard of is it)

    View Slide

  64. communicating
    sequential processes

    View Slide

  65. don’t communicate
    by sharing memory
    share memory
    by communicating

    View Slide

  66. three simple constructs

    View Slide

  67. go routines
    (lightweight threads)

    View Slide

  68. func main() {
    go greet()
    !
    // hang around a while
    time.Sleep(2 * time.Second)
    }
    !
    func greet() {
    fmt.Println("Hi!")
    }

    View Slide

  69. channels
    (for communication)

    View Slide

  70. //make a channel
    c := make(chan int)
    !
    //send on the channel
    c <- 1
    !
    //receive from the channel
    val := <- c

    View Slide

  71. func ping(c chan string) {
    for i := 0; ; i++ {
    c <- "ping"
    }
    }
    !
    func printer(c chan string) {
    for {
    msg := <- c
    fmt.Println(msg)
    time.Sleep(time.Second * 1)
    }
    }
    !
    func main() {
    c := make(chan string)
    !
    go ping(c)
    go printer(c)
    !
    time.Sleep(time.Second * 10)
    }

    View Slide

  72. func main() {
    s := make(chan int)
    !
    go greet(s)
    s <- 1
    }
    !
    func greet(signaller chan int) {
    <- signaller
    fmt.Println("Hi!")
    }

    View Slide

  73. func main() {
    functions := make(chan func(int, int)(int))
    go executor(functions)
    !
    functions <- add
    functions <- multiply
    functions <- subtract
    }
    !
    func add(x, y int) int {
    return x + y
    }
    !
    func multiply(x, y int) int {
    return x * y
    }
    !
    func subtract(x, y int) int {
    return x - y
    }
    !
    func executor(functions chan func(int, int)(int)) {
    for f := range functions {
    fmt.Println("The result is: ", f(10, 10))
    }
    }

    View Slide

  74. func main() {
    functions := make(chan func(int, int)(int))
    go executor(functions)
    !
    functions <- add
    functions <- multiply
    functions <- subtract
    }
    !
    func add(x, y int) int {
    return x + y
    }
    !
    func multiply(x, y int) int {
    return x * y
    }
    !
    func subtract(x, y int) int {
    return x - y
    }
    !
    func executor(functions chan func(int, int)(int)) {
    for f := range functions {
    fmt.Println("The result is: ", f(10, 10))
    }
    }
    The result is: 20
    The result is: 100
    The result is: 0

    View Slide

  75. select

    View Slide

  76. func printer(c chan string, d chan string) {
    for {
    select {
    case x := <- c:
    fmt.Println(x)
    case y := <- d:
    fmt.Println(y)
    case <- time.After(1 * time.Second):
    fmt.Println("Timeout!")
    }
    }
    }
    !
    func main() {
    c := make(chan string)
    d := make(chan string)
    !
    go ping(c)
    go ping(d)
    go printer(c, d)
    !
    time.Sleep(time.Second * 10)
    }

    View Slide

  77. toolchain

    View Slide

  78. % go run

    View Slide

  79. % go fix

    View Slide

  80. % go run main.go —race

    View Slide

  81. % go fmt

    View Slide

  82. % go get

    View Slide

  83. % go doc

    View Slide

  84. % go test

    View Slide

  85. what I didn’t cover…

    View Slide

  86. thanks!
    @benlovell

    View Slide