blob: 7bd2f99ac6ce4d08ee288876c058eb21eecc0bec [file] [log] [blame]
Go for Pythonistas
Francesc Campoy Flores
Gopher at Google
* Video
A recording of this talk is available.
* Goal of this talk
Whetting your appetite for Go
.image go4python/img/gopher.jpg
* My tactics
1. Showing you how Go is like Python.
2. Showing you how Go is _not_ like Python.
* Python, Go, and me
Software Engineer at Google: _Feb_11-Aug_12_
- Lots of C++ and Python.
- SQL to C++ compiler in Python.
Go Developer Relations: _Aug_12_ - ``
- Lots of Go.
* Things I don't like about Python (it'll be short)
* Beautiful and simple
Dynamic typing - nice because it's concise, like Python.
a = "hello"
b = 1
# but also
a = 2
Static typing - can be verbose, like Java or C++.
Foo foo = new Foo();
Static typing with inferred types, like Go.
a := "hello"
b := 1
// but no
a = 2
Statically-typed Python? Check [[][mypy]] and [[][Cython]].
* Run time pyrotechnics
.play go4python/ /name/,
I don't want start a flame war here but ...
- Code coverage should point you to untested cases.
- Not a way to find typos!
- 100% code coverage doesn't mean bug free.
* Other things I don't like
- Deploying - managing dependencies.
- Performance - "not too slow" is often not fast enough.
- Magic! (e.g.: `__magic__`: `**kargs`, `__getattr__`)
A list of magic methods in Python:
* And I *do* like concurrency!
A lot has been said about Python's infamous Global Interpreter Lock.
You should watch [[][Mindblowing Python GIL]], by David Beazley.
* Things I like about Python
* Things I like about Python
- The Zen of Python. ([[][Go and the Zen of Python]])
- Hashes and arrays are part of the language.
- The standard library.
- Magic! A bit of code can do a lot.
* A bit of code
Have you ever heard of Fibonacci?
.play go4python/ /fib/,
* fib.go
Something familiar?
.play go4python/fib.go /func/,
* Fibonacci without generators? What?
Python generators are awesome.
.code go4python/ /fib/,/^$/
Mechanically complex.
.play go4python/ /f = fib/,/^$/
But very easy to use.
.play go4python/ /for x/,/^$/
* Python generators
.image go4python/img/fib-py.png 500 320
Note the generator executes concurrently. Hmm... I like concurrency.
* Go concurrency
Based on *goroutines* and *channels*.
- Goroutines: very light processing actors (the gophers).
- Channels: typed, synchronized, thread-safe pipes (the arrows).
.image go4python/img/funnelin.jpg
* "Generator" goroutines
.image go4python/img/fib-go.png 500 350
* "Generator" goroutines
Uses a channel send instead of `yield`.
.code go4python/fib-gen.go /fib/,/^}/
.play go4python/fib-gen.go /main\(/,
* "Generator" goroutines
A more generator-like style:
.play go4python/fib-gen2.go /func/,
* Exercise: generating prime numbers
Write a function that returns a channel and sends the first n prime numbers on
Given the function `prime`:
.code go4python/genex.go /prime/,/^}/
Use the Go playground:
* Solution: generating prime numbers
.code go4python/genex.go /primes\(/,/^}/
.play go4python/genex.go /main\(/,
* Exercise: Fibonacci primes
Write a `filterPrimes` function that takes a channel of ints as a
parameter and returns another channel of ints.
All the prime numbers that `filterPrimes` receives from the input channel are
sent into the output channel.
Complete this code snippet:
* Solution: Fibonacci primes
.code go4python/genex2.go /filterPrimes\(/,/^}/
.play go4python/genex2.go /main\(/,
* But there's much more
Goroutines and channels aren't just for generators. They can be used to model
all kinds of concurrent systems.
To learn more:
- [[][Concurrency patterns]], by Rob Pike
- [[][Advanced Concurrency Patterns]], by Sameer Ajmani
* Object-oriented Go
* Object-oriented Go
A type declaration.
.code go4python/typesandmethods.go /Name/,/^}/
A method declaration.
.code go4python/typesandmethods.go /String/,/^}/
Constructing a `Name` and using it.
.play go4python/typesandmethods.go /William/,/Print/
* Methods on anything
There's more to types than structs.
.code go4python/typesandmethods.go /SimpleName/
You can define methods on any type.
.code go4python/typesandmethods.go /SimpleName\)/
Or almost any type.
func (s string) NoWay()
You can *only* define methods on types within the same package.
* Duck typing
* Duck typing
What defines a duck?
- Is there an explicit list of "duck" features?
- What if the duck is not exactly a duck?
s/duck/file-like object/g
* Quack?
.image go4python/img/duck.jpg 500 500
* Go interfaces
Simply a set of methods.
From the `fmt` package:
type Stringer interface {
String() string
`fmt.Println` calls the String method if the parameter is a `Stringer`.
.play go4python/typesandmethods.go /second/,/Print/
A type with all the methods of the interface implements the interface.
Structural typing: it doesn't just sound like a duck, it *is* a duck.
And that's checked at compile time.
* Decorators
* Decorators
A convenient way to wrap a function.
.code go4python/ /auth_required/,/^$/
A function can be decorated using `@`.
.code go4python/ /myHandler/,/user/
* Decorators
If we run it.
.play go4python/ /try/,
This is unauthorized:
.link http://localhost:8080/hi
This is authorized:
.link http://localhost:8080/hi?user=john
* Decorators in Go?
Not exactly, but close enough.
Go doesn't provide decorators in the language, but its function literal syntax and simple scoping rules make it easy to do something similar.
.code go4python/deco.go /hiHandler/,/^\)/
A wrapper function.
.code go4python/deco.go /authRequired/,/^$/
* Decorators in Go?
.play go4python/deco.go /func main/,/^}/
This is unauthorized:
.link http://localhost:8080/hi
This is authorized:
.link http://localhost:8080/hi?user=john
* Exercise: errors in HTTP handlers
In Go, functions can return errors to indicate that something bad happened.
The `net/http` package from the standard library defines the type `HandlerFunc`.
type HandlerFunc func(ResponseWriter, *Request)
But it's often useful to unify the error handling into a single function to avoid
.code go4python/decoex.go /errorHandler/
Write a decorator that given a `errorHandler` returns a `http.HandlerFunc`.
If an error occurs it logs it and returns an http error page.
* Exercise: errors in HTTP handlers (continuation)
Given the function `handler`.
.code go4python/decoex.go /handler/,/^}/
We want to use it as follows.
.code go4python/decoex.go /HandleFunc/
Implement `handleError` using the playground.
* Solution: errors in HTTP handlers
.code go4python/decoex.go /handleError/,/^}/
.code go4python/decoex.go /Fake/,/^$/
.play go4python/decoex.go /john/,/^$/
* Monkey patching
* Monkey patching
"A monkey patch is a way to extend or modify the run-time code of dynamic languages without altering the original source code." - _Wikipedia_
.image go4python/img/monkey.jpg 400 500
* Monkey patching
Also known as "duck punching" ... poor duck.
Often used for testing purposes.
For example, say we want to test this function:
.code go4python/ /def say_hi/,/^$/
Which depends on a function that makes an HTTP request:
.code go4python/ /def auth/,/^$/
* Monkey patching
We can test `say_hi` without making HTTP requests by stubbing out `auth`:
.play go4python/ /sayhitest/,/done/
* Gopher punching!
The same effect can be achieved in Go.
.code go4python/monkey.go /sayHi/,/^}/
Which depends on
.code go4python/monkey.go /auth /,/^}/
* Gopher punching!
Our test code can change the value of auth easily.
.play go4python/monkey.go /TestSayHi/,/^}/
* Conclusion
* Conclusion
Go is a bit like Python
- simple
- flexible
- fun
but a bit different too
- fast
- concurrent
- statically typed
- "No pythons, ducks, monkeys or gophers were harmed while writing this talk"
* Try it
Next steps
Learn Go from your browser
The community: golang-nuts