Slide 1

Slide 1 text

GO, GO, GO! GO, GO, GO! pragmatic introduction to golang pragmatic introduction to golang

Slide 2

Slide 2 text

What is Go? What is Go?

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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)

Slide 5

Slide 5 text

How does it look like? How does it look like?

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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 }

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Features Features

Slide 11

Slide 11 text

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}

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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)

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Can I haz functional programming? Can I haz functional programming?

Slide 20

Slide 20 text

yes we can yes we can

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

Concurrency Concurrency

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Wrapping up Wrapping up

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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