| Go for Pythonistas |
| |
| Francesc Campoy Flores |
| Gopher at Google |
| http://campoy.cat |
| |
| @francesc |
| campoy@golang.com |
| |
| * Video |
| |
| A recording of this talk is available. |
| |
| .link http://youtu.be/elu0VpLzJL8 |
| |
| * 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_ - `datetime.now()` |
| |
| - 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 [[http://www.mypy-lang.org/][mypy]] and [[http://cython.org/][Cython]]. |
| |
| * Run time pyrotechnics |
| |
| .play go4python/dyntyp.py /name/, |
| |
| I don't want start a flame war here but ... |
| |
| *100%*code*coverage*is*a*symptom* |
| |
| - 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: |
| |
| .link http://www.rafekettler.com/magicmethods.html |
| |
| * And I *do* like concurrency! |
| |
| A lot has been said about Python's infamous Global Interpreter Lock. |
| |
| You should watch [[http://youtu.be/ph374fJqFPE][Mindblowing Python GIL]], by David Beazley. |
| |
| * Things I like about Python |
| |
| * Things I like about Python |
| |
| - The Zen of Python. ([[/talks/2012/zen.slide#1][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 |
| |
| * fib.py |
| |
| Have you ever heard of Fibonacci? |
| |
| .play go4python/fib.py /fib/, |
| |
| * fib.go |
| |
| Something familiar? |
| |
| .play go4python/fib.go /func/, |
| |
| * Fibonacci without generators? What? |
| |
| Python generators are awesome. |
| |
| .code go4python/fib-gen.py /fib/,/^$/ |
| |
| Mechanically complex. |
| |
| .play go4python/fib-gen.py /f = fib/,/^$/ |
| |
| But very easy to use. |
| |
| .play go4python/fib-gen.py /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 |
| it. |
| |
| Given the function `prime`: |
| |
| .code go4python/genex.go /prime/,/^}/ |
| |
| Use the Go playground: |
| |
| .link /s/go4py-ex1 go.dev/s/go4py-ex1 |
| |
| * 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: |
| |
| .link /s/go4py-ex2 go.dev/s/go4py-ex2 |
| |
| * 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: |
| |
| - [[/talks/2012/concurrency.slide#1][Concurrency patterns]], by Rob Pike |
| |
| - [[/talks/2013/advconc.slide#1][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 |
| |
| _If_it_walks_like_a_duck_..._ |
| |
| 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. |
| |
| *Implicit*satisfaction*==*No*"implements"* |
| |
| 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/deco.py /auth_required/,/^$/ |
| |
| A function can be decorated using `@`. |
| |
| .code go4python/deco.py /myHandler/,/user/ |
| |
| * Decorators |
| |
| If we run it. |
| |
| .play go4python/deco.py /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 |
| repetition. |
| |
| .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. |
| |
| .link /s/go4py-ex3 go.dev/s/go4py-ex3 |
| |
| * 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/monkey.py /def say_hi/,/^$/ |
| |
| Which depends on a function that makes an HTTP request: |
| |
| .code go4python/monkey.py /def auth/,/^$/ |
| |
| * Monkey patching |
| |
| We can test `say_hi` without making HTTP requests by stubbing out `auth`: |
| |
| .play go4python/monkey.py /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 |
| |
| _Disclaimer_:_ |
| |
| - "No pythons, ducks, monkeys or gophers were harmed while writing this talk" |
| |
| * Try it |
| |
| Next steps |
| |
| .link / go.dev |
| |
| Learn Go from your browser |
| |
| .link /tour/ go.dev/tour |
| |
| The community: golang-nuts |
| |
| .link https://groups.google.com/d/forum/golang-nuts |