$30 off During Our Annual Pro Sale. View Details »

GO, GO, GO!

GO, GO, GO!

A pragmatic introduction to golang.

Adam Jodłowski

August 26, 2012
Tweet

More Decks by Adam Jodłowski

Other Decks in Programming

Transcript

  1. GO, GO, GO!
    GO, GO, GO!
    pragmatic introduction to golang
    pragmatic introduction to golang

    View Slide

  2. What is Go?
    What is Go?

    View Slide

  3. Introduction
    Introduction
    Go is a modern, general purpose open source language created
    Go is a modern, general purpose open source language created
    by Google, started in 2007 as a 20% project – released under
    by Google, started in 2007 as a 20% project – released under
    BSD­style license in November 2009
    BSD­style license in November 2009

    lightweight syntax
    lightweight syntax

    simple type system
    simple type system

    statically typed
    statically typed

    garbage­collected
    garbage­collected

    concurrent
    concurrent

    compiles to machine code
    compiles to machine code

    fast, fun & productive
    fast, fun & productive

    View Slide

  4. Selling points
    Selling points

    emphasis on simplicity (easy to learn)
    emphasis on simplicity (easy to learn)

    memory managed and syntactically lightweight
    memory managed and syntactically lightweight

    super fast compiled code (comparable to C)
    super fast compiled code (comparable to C)

    concurrency primitives (CSP­style)
    concurrency primitives (CSP­style)

    not object oriented, rather interface oriented (no classes)
    not object oriented, rather interface oriented (no classes)

    static typing
    static typing

    duck typing (type inference)
    duck typing (type inference)

    consistent standard library
    consistent standard library

    self­documenting
    self­documenting

    enforced code style
    enforced code style

    free and open source (BSD licensed)
    free and open source (BSD licensed)

    View Slide

  5. How does it look like?
    How does it look like?

    View Slide

  6. Complete, simple Go program
    Complete, simple Go program
    package
    package main
    main
    import
    import "fmt"
    "fmt"
    var
    var (
    (
    hello = "Hello"
    hello = "Hello"
    world = "World"
    world = "World"
    )
    )
    func
    func swap(a, b string) (string, string) {
    swap(a, b string) (string, string) {
    return
    return b, a
    b, a
    }
    }
    func
    func main() {
    main() {
    fmt.Println(swap(hello, world))
    fmt.Println(swap(hello, world)) // World Hello
    // World Hello
    }
    }

    View Slide

  7. Conventions
    Conventions
    Only names starting with uppercase letter are visible outside a
    Only names starting with uppercase letter are visible outside a
    package (no
    package (no public
    public or
    or private
    private visibility modifiers)
    visibility modifiers)
    Package names don't have to be globally unique (only locally)
    Package names don't have to be globally unique (only locally)
    There are no explicit getters or setters, nor
    There are no explicit getters or setters, nor field properties
    field properties
    Most of the semicolons and parentheses are gone
    Most of the semicolons and parentheses are gone
    Unused imports and variables raise compiler errors
    Unused imports and variables raise compiler errors
    Instead of
    Instead of exceptions
    exceptions, we return
    , we return error
    error values from functions
    values from functions

    View Slide

  8. No formatting hell thanks to gofmt
    No formatting hell thanks to gofmt
    go fmt
    go fmt command runs a scan & reformat operation on package
    command runs a scan & reformat operation on package
    source files, making them uniformly formatted
    source files, making them uniformly formatted
    package main
    import (
    "log"
    "fmt"
    )
    func
    main ( ){
    items , err:= SomeFunction ( "go") ;
    if (err != nil) {
    log.Fatal(err)
    }
    }
    type Item struct{
    Title string
    URL string
    Comments int
    }
    package main
    import (
    "fmt"
    "log"
    )
    func main() {
    items, err := SomeFunction("go")
    if err != nil {
    log.Fatal(err)
    }
    }
    type Item struct {
    Title string
    URL string
    Comments int
    }

    View Slide

  9. Sublime Text 2 the rescue
    Sublime Text 2 the rescue
    Sublime Text 2 + GoSublime + Gocode = WIN
    Sublime Text 2 + GoSublime + Gocode = WIN

    View Slide

  10. Features
    Features

    View Slide

  11. Type system
    Type system
    Instead of objects, Go uses
    Instead of objects, Go uses structs
    structs – collections of fields
    – collections of fields
    type
    type Point
    Point struct
    struct {
    {
    X, Y int
    X, Y int
    Name string
    Name string
    }
    }
    You can initialize struct fields using struct literal
    You can initialize struct fields using struct literal
    point
    point :=
    := Point
    Point{
    {5, 6, "starting point"
    5, 6, "starting point"}
    }
    The
    The :=
    := short variable declaration operator provides
    short variable declaration operator provides type
    type
    inference
    inference, we could use
    , we could use var point Point
    var point Point declaration instead
    declaration instead
    fmt.Printf("%v", point)
    fmt.Printf("%v", point) prints
    prints {5 6 starting point}
    {5 6 starting point}

    View Slide

  12. Maps
    Maps
    Structures mapping keys to values
    Structures mapping keys to values
    var
    var points
    points map
    map[string]Point
    [string]Point
    points =
    points = make
    make(
    (map
    map[string]Point)
    [string]Point)
    points["top"] = Point{1, 2, "starting point"}
    points["top"] = Point{1, 2, "starting point"}
    points["bottom"] = Point{3, 4, "finishing point"}
    points["bottom"] = Point{3, 4, "finishing point"}
    make()
    make() allocates and initializes memory for maps (
    allocates and initializes memory for maps (slices
    slices and
    and
    channels
    channels)
    )
    value, present = points[key]
    value, present = points[key] second boolean variable
    second boolean variable
    tells us if the key is present in the map, even if its value is zeroed
    tells us if the key is present in the map, even if its value is zeroed

    View Slide

  13. Slices
    Slices
    Slices represent arrays of values
    Slices represent arrays of values
    ints
    ints :=
    := []int{0, 1, 2, 3, 4}
    []int{0, 1, 2, 3, 4}
    fmt.Println(ints)
    fmt.Println(ints) // [0 1 2 3 4]
    // [0 1 2 3 4]
    fmt.Println(ints[1
    fmt.Println(ints[1:
    :3])
    3]) // [1 2]
    // [1 2]
    fmt.Println(ints[3
    fmt.Println(ints[3:
    :])
    ]) // [3 4]
    // [3 4]
    fmt.Println(ints[
    fmt.Println(ints[:
    :3])
    3]) // [0 1 2]
    // [0 1 2]
    Their current length may be smaller than overall capacity
    Their current length may be smaller than overall capacity
    ints
    ints :=
    := make
    make([]int, 5, 10)
    ([]int, 5, 10) // length = 5, capacity = 10
    // length = 5, capacity = 10
    We can resize slices by reassigning slices to other slices, their
    We can resize slices by reassigning slices to other slices, their
    purpose is just to point to a given chunk of underlying array
    purpose is just to point to a given chunk of underlying array

    View Slide

  14. Ranges
    Ranges
    Ranges help iterating over slices or maps in
    Ranges help iterating over slices or maps in for
    for loops
    loops
    var
    var evens = []int{0, 2, 4, 6, 8}
    evens = []int{0, 2, 4, 6, 8}
    for
    for i, v
    i, v :=
    := range
    range evens {
    evens {
    fmt.Printf("i = %d, v = %d\n", i, v)
    fmt.Printf("i = %d, v = %d\n", i, v)
    }
    }
    // output
    // output
    i = 0, v = 0
    i = 0, v = 0
    i = 1, v = 2
    i = 1, v = 2
    i = 2, v = 4
    i = 2, v = 4
    i = 3, v = 6
    i = 3, v = 6
    i = 4, v = 8
    i = 4, v = 8

    View Slide

  15. Control structures
    Control structures
    if
    if and
    and switch
    switch accept initialization statements
    accept initialization statements
    if
    if score
    score :=
    := game.Score();
    game.Score(); score > 10 {
    score > 10 {
    // end of game
    // end of game
    }
    }
    There is only one loop –
    There is only one loop – for
    for
    // classic for loop
    // classic for loop
    for
    for init; condition; post { }
    init; condition; post { }
    // while loop
    // while loop
    for
    for condition { }
    condition { }
    // infinite loop
    // infinite loop
    for
    for { }
    { }

    View Slide

  16. Better switch
    Better switch
    switch
    switch evaluates expressions instead of comparing integers,
    evaluates expressions instead of comparing integers,
    there's no automatic fallthrough* (no more
    there's no automatic fallthrough* (no more breaks
    breaks!)
    !)
    username
    username :=
    := "scott"
    "scott"
    switch
    switch username {
    username {
    case
    case "admin", "player number one":
    "admin", "player number one":
    fmt.Println("is admin")
    fmt.Println("is admin")
    default
    default:
    :
    fmt.Println("is not admin")
    fmt.Println("is not admin")
    }
    }
    switch
    switch {
    {
    case
    case 1 > 0:
    1 > 0:
    fmt.Println("1 > 0")
    fmt.Println("1 > 0")
    case
    case 1 < 0:
    1 < 0:
    fmt.Println("1 < 0")
    fmt.Println("1 < 0")
    }
    }
    * check out
    * check out fallthrough
    fallthrough statement
    statement

    View Slide

  17. Redeclaration
    Redeclaration
    You can use short declaration operator
    You can use short declaration operator :=
    := to redeclare variable
    to redeclare variable
    someValue,
    someValue, err
    err := getValue()
    := getValue()
    fmt.Println(someValue, err)
    fmt.Println(someValue, err)
    otherValue,
    otherValue, err
    err := getValue()
    := getValue()
    fmt.Println(otherValue, err)
    fmt.Println(otherValue, err)
    It's legal because once declared, variable
    It's legal because once declared, variable err
    err gets reassigned
    gets reassigned
    later (types must be compatible, the scope must be the same and
    later (types must be compatible, the scope must be the same and
    it has to be multiple assignment with at least one
    it has to be multiple assignment with at least one new
    new variable)
    variable)

    View Slide

  18. Functions
    Functions
    Functions and methods can have multiple return values
    Functions and methods can have multiple return values
    func
    func Salary(username string) (int, error) {
    Salary(username string) (int, error) {
    return
    return 666, nil
    666, nil
    }
    }
    Named result parameters allow us to use them as regular
    Named result parameters allow us to use them as regular
    variables in the function body, just like the incoming parameters
    variables in the function body, just like the incoming parameters
    func
    func Salary(username string) (
    Salary(username string) (salary
    salary int,
    int, err
    err error) {
    error) {
    salary = database.UserSalary(username)
    salary = database.UserSalary(username)
    ...
    ...
    if
    if someErrorCondition {
    someErrorCondition {
    err = errors.New("Error description")
    err = errors.New("Error description")
    }
    }
    return
    return
    }
    }

    View Slide

  19. Can I haz functional programming?
    Can I haz functional programming?

    View Slide

  20. yes we can
    yes we can

    View Slide

  21. First class functions
    First class functions
    Functions are values
    Functions are values
    var
    var calledFunction = func(param string) {
    calledFunction = func(param string) {
    fmt.Println("called with param = " + param)
    fmt.Println("called with param = " + param)
    }
    }
    func
    func callMe(callback
    callMe(callback func
    func(string)) {
    (string)) {
    result = ...
    result = ...
    callback(result)
    callback(result)
    }
    }
    // calling it in main()
    // calling it in main()
    callMe(calledFunction)
    callMe(calledFunction)
    Functions are closures, too (more on that in
    Functions are closures, too (more on that in concurrency section
    concurrency section)
    )

    View Slide

  22. Deferring function calls
    Deferring function calls
    Allows us to execute given function immediately before returning
    Allows us to execute given function immediately before returning
    from our original, enclosing function
    from our original, enclosing function
    func
    func ReadFile(filename string) (string, error) {
    ReadFile(filename string) (string, error) {
    file, err
    file, err :=
    := os.Open(filename)
    os.Open(filename)
    defer
    defer file.close()
    file.close()
    if
    if unsupportedFileEncoding {
    unsupportedFileEncoding {
    return
    return "", errors.New("Unsupported file encoding")
    "", errors.New("Unsupported file encoding")
    }
    }
    // read a file
    // read a file
    return
    return contents, nil
    contents, nil
    }
    }
    Just right before returning from
    Just right before returning from ReadFile
    ReadFile function,
    function,
    file.close()
    file.close() gets called – regardless of return path
    gets called – regardless of return path

    View Slide

  23. Methods
    Methods
    There are no classes in Go but you can define methods on types
    There are no classes in Go but you can define methods on types
    func
    func (p Point)
    (p Point) Invert() Point {
    Invert() Point {
    return
    return Point{p.Y, p.X, p.Name}
    Point{p.Y, p.X, p.Name}
    }
    }
    // calling it in main()
    // calling it in main()
    point
    point :=
    := Point{1, 2, "point"}
    Point{1, 2, "point"}
    fmt.Println(point.Invert())
    fmt.Println(point.Invert()) // {2 1 point}
    // {2 1 point}
    You can define methods on any data types (excluding basic
    You can define methods on any data types (excluding basic
    types),
    types), Go
    Go objects
    objects are just values – there is no
    are just values – there is no box
    box
    (p Point)
    (p Point) is a
    is a method receiver
    method receiver

    View Slide

  24. Interfaces
    Interfaces
    Interfaces specify behavior, define a set of methods
    Interfaces specify behavior, define a set of methods
    If a type implements those methods, it
    If a type implements those methods, it implicitly
    implicitly implements the
    implements the
    interface (no
    interface (no implements
    implements declaration)
    declaration)
    // builtin example interface
    // builtin example interface
    type
    type Stringer
    Stringer interface
    interface {
    {
    String() string
    String() string // equivalent to Java's toString()
    // equivalent to Java's toString()
    }
    }
    To consider your custom type as a given interface type, just
    To consider your custom type as a given interface type, just
    implement required methods and you're done
    implement required methods and you're done
    func
    func (p Point) String() string {
    (p Point) String() string {
    return
    return "x=" + p.X + ", y=" + p.Y
    "x=" + p.X + ", y=" + p.Y
    }
    }

    View Slide

  25. Concurrency
    Concurrency

    View Slide

  26. Don't communicate by sharing memory.
    Don't communicate by sharing memory.
    Instead, share memory by communicating.
    Instead, share memory by communicating.

    View Slide

  27. Goroutines
    Goroutines
    There are no visible condition variables, semaphores or locks
    There are no visible condition variables, semaphores or locks
    Go provides
    Go provides goroutines
    goroutines to let you run multiple computations at
    to let you run multiple computations at
    the same time and coordinate them using
    the same time and coordinate them using channels
    channels – a way of
    – a way of
    explicit communication
    explicit communication
    You can have thousands of goroutines, these are ordinary
    You can have thousands of goroutines, these are ordinary
    functions called using keyword
    functions called using keyword go
    go
    go
    go workerFunction()
    workerFunction()
    Goroutines give the efficiency of an asynchronous (event­driven)
    Goroutines give the efficiency of an asynchronous (event­driven)
    model, but you can write code in a synchronous style
    model, but you can write code in a synchronous style

    View Slide

  28. Channels
    Channels
    Channels are
    Channels are typed
    typed and used for communication between
    and used for communication between
    goroutines,
    goroutines, <-
    <- is a channel operator (send or receive)
    is a channel operator (send or receive)
    Creating a new blocking channel of type string
    Creating a new blocking channel of type string
    channel := make(
    channel := make(chan
    chan string)
    string)
    Worker function declaration (here, sending to channel only)
    Worker function declaration (here, sending to channel only)
    func
    func work(input string, results
    work(input string, results chan
    chan<- string) {
    <- string) {
    // performing work
    // performing work
    results <- result
    results <- result // sending back result
    // sending back result
    }
    }
    Unbuffered channel operations are synchronous, send/receive
    Unbuffered channel operations are synchronous, send/receive
    happens only when both sides are ready
    happens only when both sides are ready

    View Slide

  29. Synchronization
    Synchronization
    You can use channel operations to synchronize goroutines
    You can use channel operations to synchronize goroutines
    done := make(
    done := make(chan
    chan bool)
    bool)
    sort := func(s []int) {
    sort := func(s []int) {
    // sorting...
    // sorting...
    done <- true
    done <- true
    }
    }
    go
    go sort(part1)
    sort(part1)
    go
    go sort(part2)
    sort(part2)
    success1 := <- done
    success1 := <- done
    success2 := <- done
    success2 := <- done
    if
    if success1 && success2 {
    success1 && success2 {
    // great success
    // great success
    }
    }

    View Slide

  30. Worker example
    Worker example
    var
    var tasks = make(
    tasks = make(chan
    chan string, 2)
    string, 2) // capacity = 2
    // capacity = 2
    func
    func main() {
    main() {
    results := make(
    results := make(chan
    chan string, 2)
    string, 2)
    go
    go func
    func(t chan string) {
    (t chan string) { // spawn as many as you like
    // spawn as many as you like
    for
    for {
    {
    task
    task :=
    := <-
    <-t
    t // getting from channel
    // getting from channel
    // execute task synchronously...
    // execute task synchronously...
    results
    results <-
    <- task + " done"
    task + " done" // sending to channel
    // sending to channel
    }
    }
    }(tasks)
    }(tasks) // 'results' is enclosed, it's a closure!
    // 'results' is enclosed, it's a closure!
    tasks <- "task1"
    tasks <- "task1"
    tasks <- "task2"
    tasks <- "task2"
    fmt.Println(<-results)
    fmt.Println(<-results) // task1 done
    // task1 done
    fmt.Println(<-results)
    fmt.Println(<-results) // task2 done
    // task2 done
    }
    }

    View Slide

  31. Wrapping up
    Wrapping up

    View Slide

  32. Summary
    Summary
    Go is a modern, efficient and concise language by Google
    Go is a modern, efficient and concise language by Google
    It's statically typed (safe) but offers some cool features known
    It's statically typed (safe) but offers some cool features known
    from dynamic languages (duck typing, functional programming)
    from dynamic languages (duck typing, functional programming)
    You can write fast and clean code using various abstractions
    You can write fast and clean code using various abstractions
    without pointer arithmetic and memory management hassle
    without pointer arithmetic and memory management hassle
    Concurrency primitives are built into the language
    Concurrency primitives are built into the language

    View Slide

  33. Further reading
    Further reading
    Official website:
    Official website: golang.org
    golang.org
    A Tour of Go:
    A Tour of Go: tour.golang.org
    tour.golang.org
    Programming in Go: Creating
    Programming in Go: Creating
    Applications for the 21st Century
    Applications for the 21st Century
    by Mark Summerfield
    by Mark Summerfield

    View Slide

  34. Thanks!
    Thanks!
    Adam Jodłowski
    Adam Jodłowski
    jodlowski.net
    jodlowski.net

    View Slide