GO, GO, GO!

GO, GO, GO!

A pragmatic introduction to golang.

572884b36b9538ad273ef7dd7e23b228?s=128

Adam Jodłowski

August 26, 2012
Tweet

Transcript

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

    pragmatic introduction to golang
  2. What is Go? What is Go?

  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
  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)
  5. How does it look like? How does it look like?

  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 } }
  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
  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 }
  9. Sublime Text 2 the rescue Sublime Text 2 the rescue

    Sublime Text 2 + GoSublime + Gocode = WIN Sublime Text 2 + GoSublime + Gocode = WIN
  10. Features Features

  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}
  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
  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
  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
  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 { } { }
  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
  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)
  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 } }
  19. Can I haz functional programming? Can I haz functional programming?

  20. yes we can yes we can

  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) )
  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
  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
  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 } }
  25. Concurrency Concurrency

  26. Don't communicate by sharing memory. Don't communicate by sharing memory.

    Instead, share memory by communicating. Instead, share memory by communicating.
  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
  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
  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 } }
  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 } }
  31. Wrapping up Wrapping up

  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
  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
  34. Thanks! Thanks! Adam Jodłowski Adam Jodłowski jodlowski.net jodlowski.net