Go
Lightning talk 2017-11-23
● Created by Google for Google scale problems
● First class concurrency support
● Easy to learn, easy to use
● Good performance by default
● C++ too hard, Python too slow, few enjoyed Java
Background
● Strong, static typed language
● Garbage Collected
● Compiles to a binary
● Easy cross compilation
What is it?
Saker Go inte har:
● Klasser
● Konstruktorer/destruktorer
● Ineheritance
● Exceptions
● Annotations
● Generics
● (100% bakåtkompatibelt så länge 1.X)
Core feature: simplicity
● Rankar runt 15:e största språk
● Rankade 9 på Github PRs
● Enda språket topp 5 “most wanted” och “most
loved” på Stack Overflow Survey 2017
● Används av ex Dropbox, Cloudflare,
DigitalOcean, Docker, Google
Popularitet
// Separate init and declaration
var i int // will be set to int default (0)
i = 123
var i int = 123 // Above in one line
i := 123 // Shorthand, type inferred (int)
str := “‫”مرحبا‬ // UTF-8 strings
strPtr := &str // & will create pointer to value
var anotherString string
anotherString = *strPtr // * dereferences pointer
const MEETUP_NAME = “Go West”
Types
// map int -> string
myMap := map[int]string{}
myMap[1] = “Go”
// Array of fixed size 3
myArray := [3]string{"Go","West", “introduction”}
myArray[1] // “West”
myArray[10] // panic!
// Non preallocated slice
var mySlice []string // len(mySlice) = 0
mySlice = append(mySlice, “hi”) // len = 1
mySlice[2] = “there” // panic!
// Pre allocated slice
myAllocatedSlice := make([]string, 10) // len 10
myAllocatedSlice[2] = “Hi” // ok!
More complex types
Create types
type Status string // “Fake” enum
const (
Active Status = “active”
Inactive Status = “inactive”
)
type User struct {
Username string
Status Status // instead of string
Profile Profile
}
type Profile struct {
Bio string
}
u := User{
Username: “gust1n”,
Status: Active,
Profile: Profile{
Bio: “Gopher”,
},
}
u.Status = “inactive” // wont compile
Functions
// Simple example
func greet(name string) string {
return “hello ” + name
}
greeting := greet(“Joakim”) // hello Joakim
// Multiple returns
func multiple() (int, int) {
return 0,8
}
first, second := multiple() // first: 0, second: 8
// Variadic functions
func greet(names ...string) {}
greet(“Joakim”, “Susan”, “Ahmed”)
Pointers
u := User{Username: “gust1n”, Status: Inactive}
func activate(u User) {
u.Profile.Status = Active // No effect
}
func activatePtr(u *User) {
u.Profile.Status = Active // Success!
}
func changeUser(u *User) {
u = &User{Username: “Go West”} // No effect
}
activate(u) // u.Profile.Status: Inactive
activatePtr(&u) // u.Profile.Status: Active
changeUser(&u) // u.Profile.Username: gust1n
Methods
func (u *User) activate() {
u.Profile.Status = ACTIVE
}
u := User{Username: “gust1n”, Status: INACTIVE}
u.activate() // Profit!
Concurrency: Blocking
func somethingSlow() {
time.Sleep(10 * time.Second)
fmt.Println(“slow done”)
}
func main() {
somethingSlow()
fmt.Println(“done!”)
}
// output:
// (will wait 10s)
// slow done
// done
// (exit)
Concurrency: go keyword
func somethingSlow() {
time.Sleep(10 * time.Second)
fmt.Println(“slow done”)
}
func main() {
go somethingSlow()
fmt.Println(“done!”)
}
// output:
// done
// (exit)
Concurrency: data races
func calculateTotal(total int, next int) {
total = total + next
}
func main() {
var total int
for i := 0; i < 3; i++ {
go calculateTotal(total, i)
}
fmt.Printf(“total is %d”, total)
}
Concurrency: use mutex?
var lock sync.Mutex
func calculateTotal(total int, next int) {
lock.Lock()
total = total + next
lock.Unlock()
}
func main() {
var total int
for i := 0; i < 3; i++ {
go calculateTotal(total, i)
}
fmt.Printf(“total is %d”, total)
}
Concurrency: channels
// A channel is for communicating between goroutines
intCh := make(chan int, 1)
// A channel can be written to
intCh <- 1337
// and read from (blocking)
i := <- intCh
// Think of it as a pipeline of any type
userCh := make(chan *User, 1)
// Are totally safe for concurrent access
go func() {
intCh <- 1337
}()
Concurrency: orchestration
func calculateNext(resCh chan int, next int) {
resCh <- next
}
func main() {
resCh := make(chan int, 1)
for i := 0; i < 3; i++ {
go calculateNext(resCh, i)
}
var total int
for i := 0; i < 3; i++ {
next := <-resCh // blocks until channel written to
total = total + next
}
fmt.Printf(“total is %d”, total)
}
Concurrency: orchestration cont.
respCh := make(chan int, 1)
doSomethingSlow(respCh)
// blocking
select {
case resp := <-respCh:
// do something with resp
case time.After(2 * time.Second):
// timeout, move on
}
Real world example
package uptime
type Response struct {
URL string
StatusCode int
Duration time.Duration
}
func Check(respCh chan Response, URL string) {
start := time.Now()
resp, _ := http.Get(URL)
respCh <- Response{
URL: URL,
StatusCode:
resp.StatusCode,
Duration: time.Since(start),
}
}
package main
import (
“fmt”
“github.com/gust1n/uptime”
)
func main() {
URLs := []string{
“https://www.golang.org”,
“https://www.rust-lang.org/”,
“http://elixir-lang.github.io/”,
}
respCh := make(chan uptime.Response, 1)
for _, URL := range URLs {
go uptime.Check(respCh, URL)
}
for i := 0; i < len(URLs); i++ {
resp := <- respCh
fmt.Printf(“%s (%d) - %sn”,
resp.URL,
resp.StatusCode,
resp.Duration.String(),
)
}
}

Lightning talk: Go

  • 1.
  • 2.
    ● Created byGoogle for Google scale problems ● First class concurrency support ● Easy to learn, easy to use ● Good performance by default ● C++ too hard, Python too slow, few enjoyed Java Background
  • 3.
    ● Strong, statictyped language ● Garbage Collected ● Compiles to a binary ● Easy cross compilation What is it?
  • 4.
    Saker Go intehar: ● Klasser ● Konstruktorer/destruktorer ● Ineheritance ● Exceptions ● Annotations ● Generics ● (100% bakåtkompatibelt så länge 1.X) Core feature: simplicity
  • 5.
    ● Rankar runt15:e största språk ● Rankade 9 på Github PRs ● Enda språket topp 5 “most wanted” och “most loved” på Stack Overflow Survey 2017 ● Används av ex Dropbox, Cloudflare, DigitalOcean, Docker, Google Popularitet
  • 6.
    // Separate initand declaration var i int // will be set to int default (0) i = 123 var i int = 123 // Above in one line i := 123 // Shorthand, type inferred (int) str := “‫”مرحبا‬ // UTF-8 strings strPtr := &str // & will create pointer to value var anotherString string anotherString = *strPtr // * dereferences pointer const MEETUP_NAME = “Go West” Types
  • 7.
    // map int-> string myMap := map[int]string{} myMap[1] = “Go” // Array of fixed size 3 myArray := [3]string{"Go","West", “introduction”} myArray[1] // “West” myArray[10] // panic! // Non preallocated slice var mySlice []string // len(mySlice) = 0 mySlice = append(mySlice, “hi”) // len = 1 mySlice[2] = “there” // panic! // Pre allocated slice myAllocatedSlice := make([]string, 10) // len 10 myAllocatedSlice[2] = “Hi” // ok! More complex types
  • 8.
    Create types type Statusstring // “Fake” enum const ( Active Status = “active” Inactive Status = “inactive” ) type User struct { Username string Status Status // instead of string Profile Profile } type Profile struct { Bio string } u := User{ Username: “gust1n”, Status: Active, Profile: Profile{ Bio: “Gopher”, }, } u.Status = “inactive” // wont compile
  • 9.
    Functions // Simple example funcgreet(name string) string { return “hello ” + name } greeting := greet(“Joakim”) // hello Joakim // Multiple returns func multiple() (int, int) { return 0,8 } first, second := multiple() // first: 0, second: 8 // Variadic functions func greet(names ...string) {} greet(“Joakim”, “Susan”, “Ahmed”)
  • 10.
    Pointers u := User{Username:“gust1n”, Status: Inactive} func activate(u User) { u.Profile.Status = Active // No effect } func activatePtr(u *User) { u.Profile.Status = Active // Success! } func changeUser(u *User) { u = &User{Username: “Go West”} // No effect } activate(u) // u.Profile.Status: Inactive activatePtr(&u) // u.Profile.Status: Active changeUser(&u) // u.Profile.Username: gust1n
  • 11.
    Methods func (u *User)activate() { u.Profile.Status = ACTIVE } u := User{Username: “gust1n”, Status: INACTIVE} u.activate() // Profit!
  • 12.
    Concurrency: Blocking func somethingSlow(){ time.Sleep(10 * time.Second) fmt.Println(“slow done”) } func main() { somethingSlow() fmt.Println(“done!”) } // output: // (will wait 10s) // slow done // done // (exit)
  • 13.
    Concurrency: go keyword funcsomethingSlow() { time.Sleep(10 * time.Second) fmt.Println(“slow done”) } func main() { go somethingSlow() fmt.Println(“done!”) } // output: // done // (exit)
  • 14.
    Concurrency: data races funccalculateTotal(total int, next int) { total = total + next } func main() { var total int for i := 0; i < 3; i++ { go calculateTotal(total, i) } fmt.Printf(“total is %d”, total) }
  • 15.
    Concurrency: use mutex? varlock sync.Mutex func calculateTotal(total int, next int) { lock.Lock() total = total + next lock.Unlock() } func main() { var total int for i := 0; i < 3; i++ { go calculateTotal(total, i) } fmt.Printf(“total is %d”, total) }
  • 16.
    Concurrency: channels // Achannel is for communicating between goroutines intCh := make(chan int, 1) // A channel can be written to intCh <- 1337 // and read from (blocking) i := <- intCh // Think of it as a pipeline of any type userCh := make(chan *User, 1) // Are totally safe for concurrent access go func() { intCh <- 1337 }()
  • 17.
    Concurrency: orchestration func calculateNext(resChchan int, next int) { resCh <- next } func main() { resCh := make(chan int, 1) for i := 0; i < 3; i++ { go calculateNext(resCh, i) } var total int for i := 0; i < 3; i++ { next := <-resCh // blocks until channel written to total = total + next } fmt.Printf(“total is %d”, total) }
  • 18.
    Concurrency: orchestration cont. respCh:= make(chan int, 1) doSomethingSlow(respCh) // blocking select { case resp := <-respCh: // do something with resp case time.After(2 * time.Second): // timeout, move on }
  • 19.
    Real world example packageuptime type Response struct { URL string StatusCode int Duration time.Duration } func Check(respCh chan Response, URL string) { start := time.Now() resp, _ := http.Get(URL) respCh <- Response{ URL: URL, StatusCode: resp.StatusCode, Duration: time.Since(start), } } package main import ( “fmt” “github.com/gust1n/uptime” ) func main() { URLs := []string{ “https://www.golang.org”, “https://www.rust-lang.org/”, “http://elixir-lang.github.io/”, } respCh := make(chan uptime.Response, 1) for _, URL := range URLs { go uptime.Check(respCh, URL) } for i := 0; i < len(URLs); i++ { resp := <- respCh fmt.Printf(“%s (%d) - %sn”, resp.URL, resp.StatusCode, resp.Duration.String(), ) } }