1 / 40 Do I need to switch to Go(lang) Max Tepkeev 20 July 2016 Bilbao, Spain
2 / 40 About me Max Tepkeev Russia, Moscow • python-redmine • architect • instructions https://www.github.com/maxtepkeev
3 / 40 About us Aidata – online and offline user data collection and analysis 1 000 000 000 unique users per month http://www.aidata.me
4 / 40 About us
5 / 40 Why switch from Python • Speed • Concurrency • GIL • No ”true” binaries • Dynamic types
6 / 40 Language requirements • Modern • Fast • Easy • Compiled • Statically typed • Support main platforms
7 / 40 Why Go StackOverflow questions by tag*: • Go: 16795 (1113) • Rust: 4226 (429) • D: 2025 (34) • Nim: 136 (8) * as of 19 July 2016
8 / 40 Popularity
9 / 40 Go • Created in Google • Open-sourced in November 2009 • Designed by smart people: • Robert Griesemer • Rob Pike • Ken Thompson https://talks.golang.org/2012/splash.article
10 / Who uses Go • Google • Dropbox • Facebook • IBM • Intel • SpaceX • Uber • VMware • Yahoo • Twitter • Heroku • DigitalOcean https://github.com/golang/go/wiki/GoUsers
11 / 40 Project layout $GOPATH/ bin/ hello # command executable outyet # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object src/ github.com/golang/example/ .git/ # Git repository metadata hello/ hello.go # command source outyet/ main.go # command source stringutil/ reverse.go # package source
12 / Package management $ go get github.com/golang/example src/ github.com/golang/example/ .git/ hello/ hello.go outyet/ main.go stringutil/ reverse.go
13 / Package management • vendoring • gopkg.in • getgb.io github.com/tools/godep github.com/gpmgo/gopm github.com/pote/gpm github.com/nitrous-io/goop github.com/alouche/rodent github.com/jingweno/nut github.com/niemeyer/gopkg github.com/mjibson/party github.com/kardianos/vendor github.com/kisielk/vendorize github.com/mattn/gom github.com/dkulchenko/bunch github.com/skelterjohn/wgo github.com/Masterminds/glide github.com/robfig/glock bitbucket.org/vegansk/gobs launchpad.net/godeps github.com/d2fn/gopack github.com/laher/gopin github.com/LyricalSecurity/gigo github.com/VividCortex/johnny-deps
14 / Commands • go fmt • go test • go fix • go run • go run -race • go vet
15 / Hello World $GOPATH/src/github.com/user/hello/hello.go: package main import "fmt" func main() { fmt.Println("Hello, world.") } $ go install github.com/user/hello $ $GOPATH/bin/hello Hello, world.
16 / Comparison: Imports Go import "os" import ( "os" "compress/gzip" ) import os1 "os" Python import os import os import gzip import os as os1
17 / Comparison: Import Names Go import "os" os.Getwd() Python import os os.getcwd()
18 / Comparison: Types Go var ( b bool = true s string = "hey" si int = -1 ui uint = 1 f float32 = 1.0 c complex64 = 3i l []int = []int{1, 2} m map[int]int = map[int]int{1: 1} ) Python b = True s = "hey" si = 1 ui = -1 f = 1.0 c = 3j l = [1, 2] m = {1:1}
19 / Comparison: Variables Go var ( i = 1 j = "hey" ) i := 1 j := "hey” i, j := 1, "hey" Python i = 1 j = "hey” i, j = 1, "hey"
20 / Comparison: 1st Class Functions Go func add(x, y int) int { return x + y } add := func (x, y int) int { return x + y } Python def add(x, y): return x + y add = lambda x, y: x + y
21 / Comparison: Optional args Go func sum(nums ...int) { result := 0 for _, num := range nums { result += num } return result } sum(1, 2, 3) sum([]int{1, 2, 3}...) Python def sum(*nums): result = 0 for num in nums: result += num return result sum(1, 2, 3) sum(*[1, 2, 3])
22 / Comparison: Optional kwargs Go type Kwargs struct { foo, bar string } func join(kw Kwargs) string { if kw.foo == "" {kw.foo = "foo"} if kw.bar == "" {kw.bar = "bar"} return kw.foo + kw.bar } join(Kwargs{}) join(Kwargs{bar: "foo"}) Python def join(foo=None, bar=None): if foo is None: foo = 'foo' if bar is None: bar = 'bar' return foo + bar join() join(bar='foo')
23 / Comparison: Loops Go seq := []int{1, 2, 3} for _, x := range seq { fmt.Println(x) } Python seq = [1, 2, 3] for x in seq: print x
24 / Comparison: Loops Go seq := []int{1, 2, 3} for i := 0; i < len(seq); i++ { fmt.Println(seq[i]) } Python seq = [1, 2, 3] num, count = 0, len(seq) while num < count: print seq[num] num += 1
25 / Comparison: Loops Go for { fmt.Println("Go rocks") } Python while True: print "Python rocks"
26 / Comparison: Comprehensions Go word := "hello" chars := []string{} for _, char := range word { chars = append(chars, string(char)) } fmt.Println(chars) // [h e l l o] Python word = "hello" chars = [char for char in word] print chars # ['h', 'e', 'l', 'l', 'o']
27 / Comparison: Conditionals Go if x := 1; x > 0 { fmt.Println(x) } else { fmt.Println("Sorry") } Python x = 1 if x > 0: print x else: print "Sorry"
28 / Comparison: Conditionals Go switch x := 1; { case x < 0: fmt.Println("Negative") case x > 0: fmt.Println("Positive") default: fmt.Println("Zero") } Python x = 1 if x > 0: print "Positive" elif x < 0: print "Negative" else: print "Zero"
29 / Comparison: Slicing Go seq := []int{1, 2, 3, 4, 5} fmt.Print(seq[:2]) // [1 2] fmt.Print(seq[3:]) // [4 5] fmt.Print(seq[2:3]) // [3] Python seq = [1, 2, 3, 4, 5] print seq[:2] # [1, 2] print seq[3:] # [4, 5] print seq[2:3] # [3]
30 / Comparison: Error Handling Go conn, err := db.Connect() if err != nil { fmt.Print("Can't connect") } panic() / recover() Python try: conn = db.Connect() except ConnectionError: print "Can't connect"
31 / Comparison: Classes Go type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf( "%s: %d", p.Name, p.Age) } p := Person{"Batman", 45} fmt.Println(p) // Batman: 45 Python class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "{}: {}".format( self.name, self.age) p = Person("Batman", 45) print p # Batman: 45
32 / Comparison: Constructors Go type Person struct { Name string Age int } func NewPerson(n string, a int) *Person { return &Person{Name: n, Age: a} } p := NewPerson("Batman", 45) Python class Person(object): def __init__(self, name, age): self.name = name self.age = age p = Person("Batman", 45)
33 / Comparison: Inheritance Go type Person struct{ Name string } type Doctor struct{ Person } func (p Person) Eat() { fmt.Println("Eating") } func (d Doctor) Heal() { fmt.Println("Healing") } d := Doctor{Person{"Gregory House"}} d.Eat() // Eating d.Heal() // Healing Python class Person(object): def __init__(self, name): self.name = name def eat(self): print "Eating" class Doctor(Person): def heal(self): print "Healing" d = Doctor("Gregory House") d.eat() # "Eating" d.heal() # "Healing"
34 / Comparison: Cleanup Go func readFile() (result string) { fpath := "/tmp/file" f, err := os.Open(fpath) if err != nil { panic(err) } defer f.Close() // reading file here return result } Python def read_file(): result = None fpath = "/tmp/file" with open(fpath) as f: result = f.read() # file is closed here return result
35 / Comparison: Concurrent progs Go urls := []string{"http://python.org", "http://golang.org"} responses := make(chan string) for _, url := range urls { go func(url string) { resp, _ := http.Get(url) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) responses <- string(body) }(url) } for response := range responses { fmt.Println(response) } Python urls = ['http://python.org', 'http://golang.org'] async def fetch(session, url): async with session.get(url) as response: return await response.read() async def fetch_all(session, urls, loop): tasks = [fetch(session, url) for url in urls] return await asyncio.gather(*tasks) loop = asyncio.get_event_loop() with aiohttp.ClientSession(loop=loop) as session: responses = loop.run_until_complete( fetch_all(session, urls, loop)) print(responses)
36 / More Go features • make() / new() • Arrays • Pointers • Interfaces • Type assertions • Type switches • Buffered channels / select statement • Unsafe package • Cross compilation
37 / Python features Go lacks • list / dict comprehensions • generators • decorators • exceptions • metaclasses • descriptors • __magic__ methods • set / tuple
38 / Conclusion Go + Good standard library + 3rd Party libs for almost everything + Compiled + Statically typed + Built-in concurrency - Verbose - No syntactic sugar - No Soul Python + Good standard library + 3rd Party libs for everything + Less code + Syntactic sugar + Has Soul - Interpreted - Dynamically typed - Concurrency
39 / Go Useful Links 1. https://tour.golang.org/ 2. http://golang.org/doc/effective_go.html 3. https://play.golang.org/ 4. http://golangweekly.com/ 5. http://devs.cloudimmunity.com/gotchas- and-common-mistakes-in-go-golang/
40 / Questions slides: http://slideshare.net/maxtepkeev github: https://github.com/maxtepkeev email: tepkeev@gmail.com skype: max.tepkeev company: http://www.aidata.me

EuroPython 2016 - Do I Need To Switch To Golang

  • 1.
    1 / 40 DoI need to switch to Go(lang) Max Tepkeev 20 July 2016 Bilbao, Spain
  • 2.
    2 / 40 Aboutme Max Tepkeev Russia, Moscow • python-redmine • architect • instructions https://www.github.com/maxtepkeev
  • 3.
    3 / 40 Aboutus Aidata – online and offline user data collection and analysis 1 000 000 000 unique users per month http://www.aidata.me
  • 4.
  • 5.
    5 / 40 Whyswitch from Python • Speed • Concurrency • GIL • No ”true” binaries • Dynamic types
  • 6.
    6 / 40 Languagerequirements • Modern • Fast • Easy • Compiled • Statically typed • Support main platforms
  • 7.
    7 / 40 WhyGo StackOverflow questions by tag*: • Go: 16795 (1113) • Rust: 4226 (429) • D: 2025 (34) • Nim: 136 (8) * as of 19 July 2016
  • 8.
  • 9.
    9 / 40 Go •Created in Google • Open-sourced in November 2009 • Designed by smart people: • Robert Griesemer • Rob Pike • Ken Thompson https://talks.golang.org/2012/splash.article
  • 10.
    10 / Who usesGo • Google • Dropbox • Facebook • IBM • Intel • SpaceX • Uber • VMware • Yahoo • Twitter • Heroku • DigitalOcean https://github.com/golang/go/wiki/GoUsers
  • 11.
    11 / 40 Projectlayout $GOPATH/ bin/ hello # command executable outyet # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object src/ github.com/golang/example/ .git/ # Git repository metadata hello/ hello.go # command source outyet/ main.go # command source stringutil/ reverse.go # package source
  • 12.
    12 / Package management $go get github.com/golang/example src/ github.com/golang/example/ .git/ hello/ hello.go outyet/ main.go stringutil/ reverse.go
  • 13.
    13 / Package management •vendoring • gopkg.in • getgb.io github.com/tools/godep github.com/gpmgo/gopm github.com/pote/gpm github.com/nitrous-io/goop github.com/alouche/rodent github.com/jingweno/nut github.com/niemeyer/gopkg github.com/mjibson/party github.com/kardianos/vendor github.com/kisielk/vendorize github.com/mattn/gom github.com/dkulchenko/bunch github.com/skelterjohn/wgo github.com/Masterminds/glide github.com/robfig/glock bitbucket.org/vegansk/gobs launchpad.net/godeps github.com/d2fn/gopack github.com/laher/gopin github.com/LyricalSecurity/gigo github.com/VividCortex/johnny-deps
  • 14.
    14 / Commands • gofmt • go test • go fix • go run • go run -race • go vet
  • 15.
    15 / Hello World $GOPATH/src/github.com/user/hello/hello.go: packagemain import "fmt" func main() { fmt.Println("Hello, world.") } $ go install github.com/user/hello $ $GOPATH/bin/hello Hello, world.
  • 16.
    16 / Comparison: Imports Go import"os" import ( "os" "compress/gzip" ) import os1 "os" Python import os import os import gzip import os as os1
  • 17.
    17 / Comparison: ImportNames Go import "os" os.Getwd() Python import os os.getcwd()
  • 18.
    18 / Comparison: Types Go var( b bool = true s string = "hey" si int = -1 ui uint = 1 f float32 = 1.0 c complex64 = 3i l []int = []int{1, 2} m map[int]int = map[int]int{1: 1} ) Python b = True s = "hey" si = 1 ui = -1 f = 1.0 c = 3j l = [1, 2] m = {1:1}
  • 19.
    19 / Comparison: Variables Go var( i = 1 j = "hey" ) i := 1 j := "hey” i, j := 1, "hey" Python i = 1 j = "hey” i, j = 1, "hey"
  • 20.
    20 / Comparison: 1stClass Functions Go func add(x, y int) int { return x + y } add := func (x, y int) int { return x + y } Python def add(x, y): return x + y add = lambda x, y: x + y
  • 21.
    21 / Comparison: Optionalargs Go func sum(nums ...int) { result := 0 for _, num := range nums { result += num } return result } sum(1, 2, 3) sum([]int{1, 2, 3}...) Python def sum(*nums): result = 0 for num in nums: result += num return result sum(1, 2, 3) sum(*[1, 2, 3])
  • 22.
    22 / Comparison: Optionalkwargs Go type Kwargs struct { foo, bar string } func join(kw Kwargs) string { if kw.foo == "" {kw.foo = "foo"} if kw.bar == "" {kw.bar = "bar"} return kw.foo + kw.bar } join(Kwargs{}) join(Kwargs{bar: "foo"}) Python def join(foo=None, bar=None): if foo is None: foo = 'foo' if bar is None: bar = 'bar' return foo + bar join() join(bar='foo')
  • 23.
    23 / Comparison: Loops Go seq:= []int{1, 2, 3} for _, x := range seq { fmt.Println(x) } Python seq = [1, 2, 3] for x in seq: print x
  • 24.
    24 / Comparison: Loops Go seq:= []int{1, 2, 3} for i := 0; i < len(seq); i++ { fmt.Println(seq[i]) } Python seq = [1, 2, 3] num, count = 0, len(seq) while num < count: print seq[num] num += 1
  • 25.
    25 / Comparison: Loops Go for{ fmt.Println("Go rocks") } Python while True: print "Python rocks"
  • 26.
    26 / Comparison: Comprehensions Go word:= "hello" chars := []string{} for _, char := range word { chars = append(chars, string(char)) } fmt.Println(chars) // [h e l l o] Python word = "hello" chars = [char for char in word] print chars # ['h', 'e', 'l', 'l', 'o']
  • 27.
    27 / Comparison: Conditionals Go ifx := 1; x > 0 { fmt.Println(x) } else { fmt.Println("Sorry") } Python x = 1 if x > 0: print x else: print "Sorry"
  • 28.
    28 / Comparison: Conditionals Go switchx := 1; { case x < 0: fmt.Println("Negative") case x > 0: fmt.Println("Positive") default: fmt.Println("Zero") } Python x = 1 if x > 0: print "Positive" elif x < 0: print "Negative" else: print "Zero"
  • 29.
    29 / Comparison: Slicing Go seq:= []int{1, 2, 3, 4, 5} fmt.Print(seq[:2]) // [1 2] fmt.Print(seq[3:]) // [4 5] fmt.Print(seq[2:3]) // [3] Python seq = [1, 2, 3, 4, 5] print seq[:2] # [1, 2] print seq[3:] # [4, 5] print seq[2:3] # [3]
  • 30.
    30 / Comparison: ErrorHandling Go conn, err := db.Connect() if err != nil { fmt.Print("Can't connect") } panic() / recover() Python try: conn = db.Connect() except ConnectionError: print "Can't connect"
  • 31.
    31 / Comparison: Classes Go typePerson struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf( "%s: %d", p.Name, p.Age) } p := Person{"Batman", 45} fmt.Println(p) // Batman: 45 Python class Person(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "{}: {}".format( self.name, self.age) p = Person("Batman", 45) print p # Batman: 45
  • 32.
    32 / Comparison: Constructors Go typePerson struct { Name string Age int } func NewPerson(n string, a int) *Person { return &Person{Name: n, Age: a} } p := NewPerson("Batman", 45) Python class Person(object): def __init__(self, name, age): self.name = name self.age = age p = Person("Batman", 45)
  • 33.
    33 / Comparison: Inheritance Go typePerson struct{ Name string } type Doctor struct{ Person } func (p Person) Eat() { fmt.Println("Eating") } func (d Doctor) Heal() { fmt.Println("Healing") } d := Doctor{Person{"Gregory House"}} d.Eat() // Eating d.Heal() // Healing Python class Person(object): def __init__(self, name): self.name = name def eat(self): print "Eating" class Doctor(Person): def heal(self): print "Healing" d = Doctor("Gregory House") d.eat() # "Eating" d.heal() # "Healing"
  • 34.
    34 / Comparison: Cleanup Go funcreadFile() (result string) { fpath := "/tmp/file" f, err := os.Open(fpath) if err != nil { panic(err) } defer f.Close() // reading file here return result } Python def read_file(): result = None fpath = "/tmp/file" with open(fpath) as f: result = f.read() # file is closed here return result
  • 35.
    35 / Comparison: Concurrentprogs Go urls := []string{"http://python.org", "http://golang.org"} responses := make(chan string) for _, url := range urls { go func(url string) { resp, _ := http.Get(url) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) responses <- string(body) }(url) } for response := range responses { fmt.Println(response) } Python urls = ['http://python.org', 'http://golang.org'] async def fetch(session, url): async with session.get(url) as response: return await response.read() async def fetch_all(session, urls, loop): tasks = [fetch(session, url) for url in urls] return await asyncio.gather(*tasks) loop = asyncio.get_event_loop() with aiohttp.ClientSession(loop=loop) as session: responses = loop.run_until_complete( fetch_all(session, urls, loop)) print(responses)
  • 36.
    36 / More Gofeatures • make() / new() • Arrays • Pointers • Interfaces • Type assertions • Type switches • Buffered channels / select statement • Unsafe package • Cross compilation
  • 37.
    37 / Python featuresGo lacks • list / dict comprehensions • generators • decorators • exceptions • metaclasses • descriptors • __magic__ methods • set / tuple
  • 38.
    38 / Conclusion Go + Goodstandard library + 3rd Party libs for almost everything + Compiled + Statically typed + Built-in concurrency - Verbose - No syntactic sugar - No Soul Python + Good standard library + 3rd Party libs for everything + Less code + Syntactic sugar + Has Soul - Interpreted - Dynamically typed - Concurrency
  • 39.
    39 / Go UsefulLinks 1. https://tour.golang.org/ 2. http://golang.org/doc/effective_go.html 3. https://play.golang.org/ 4. http://golangweekly.com/ 5. http://devs.cloudimmunity.com/gotchas- and-common-mistakes-in-go-golang/
  • 40.
    40 / Questions slides: http://slideshare.net/maxtepkeev github:https://github.com/maxtepkeev email: tepkeev@gmail.com skype: max.tepkeev company: http://www.aidata.me