| Go for Javaneros (Javaïstes?) |
| #go4java |
| |
| Francesc Campoy |
| Gopher and Developer Advocate |
| Google |
| @francesc |
| campoy@golang.org |
| |
| * What is Go? |
| |
| Go is an open-source programming language |
| |
| - created at Google, |
| - to solve Google-scale problems. |
| |
| .image go4java/img/gopher.jpg 450 _ |
| |
| * Who uses Go? |
| |
| Google: |
| |
| - YouTube |
| - dl.google.com |
| |
| Others: |
| |
| - dotCloud (Docker) |
| - SoundCloud |
| - Canonical |
| - CloudFlare |
| - Mozilla |
| - ... |
| |
| [[http://golang.org/wiki/GoUsers][golang.org/wiki/GoUsers]] |
| |
| * Who uses Go? |
| |
| .image go4java/img/trends.png _ 800 |
| |
| .caption Google Trends for [[http://www.google.com/trends/explore#q=golang][golang]] |
| |
| * Why Go? |
| |
| * Simplicity |
| |
| Minimal design |
| |
| .image go4java/img/perfection.jpg |
| |
| * Consistency |
| |
| Orthogonal features |
| |
| .image go4java/img/lego.jpg 400 _ |
| |
| .caption By Kenny Louie from Vancouver, Canada [[http://creativecommons.org/licenses/by/2.0][CC-BY-2.0]], via Wikimedia Commons |
| |
| * Readability |
| |
| “The ratio of time spent reading (code) versus writing is well over 10 to 1 ... (therefore) making it easy to read makes it easier to write.” |
| ― Robert C. Martin |
| |
| .image go4java/img/piet.png 500 600 |
| |
| * Safety |
| |
| Type safety, no buffer overflows, no pointer arithmetic. |
| |
| .image go4java/img/baby.jpg 500 500 |
| |
| * Built-in concurrency features |
| |
| “In a concurrent world, imperative is the wrong default!” - Tim Sweeney |
| |
| Communicating Sequential Processes - Hoare (1978) |
| |
| .image go4java/img/conc.jpg _ 1000 |
| |
| * Speed |
| |
| .image go4java/img/fast.jpg 500 _ |
| |
| * Let's dive in |
| |
| * Go and Java common aspects |
| |
| Go and Java are |
| |
| - object oriented |
| |
| - garbage collected |
| |
| - statically typed |
| |
| - part of the C family |
| |
| * Object oriented flavors |
| |
| Go is Object Oriented, but doesn't have the keywords: |
| |
| - `class`, |
| - `extends`, or |
| - `implements`. |
| |
| * All types are created equal |
| |
| * Go types |
| |
| - primitive types |
| |
| int, uint, int8, uint8, ... |
| bool, string |
| float32, float64 |
| complex64, complex128 |
| |
| - structs |
| |
| struct { |
| Name string |
| Age int |
| } |
| |
| - slices and arrays |
| |
| []int, [3]string, []struct{ Name string } |
| |
| - maps |
| |
| map[string]int |
| |
| * Kinds of types (continued) |
| |
| - pointers |
| |
| *int, *Person |
| |
| - functions |
| |
| func(int, int) int |
| |
| - channels |
| |
| chan bool |
| |
| - interfaces |
| |
| interface { |
| Start() |
| Stop() |
| } |
| |
| * Type declarations |
| |
| type [name] [specification] |
| |
| `Person` is a `struct` type. |
| |
| type Person struct { |
| name string |
| age int |
| } |
| |
| `Celsius` is a `float64` type. |
| |
| type Celsius float64 |
| |
| * Function declarations |
| |
| func [name] ([params]) [return value] |
| func [name] ([params]) ([return values]) |
| |
| A sum function: |
| |
| func sum(a int, b int) int { |
| return a + b |
| } |
| |
| A function with multiple returned values: |
| |
| func div(a, b int) (int, int) |
| return a / b, a % b |
| } |
| |
| Made clearer by naming the return values: |
| |
| func div(den, div int) (q, rem int) |
| return a / b, a % b |
| } |
| |
| * Method declarations |
| |
| func ([receiver]) [name] ([params]) ([return values]) |
| |
| A method on a struct: |
| |
| func (p Person) Major() bool { |
| return p.age >= 18 |
| } |
| |
| But also a method on a `float64`: |
| |
| func (c Celsius) Freezing() bool { |
| return c <= 0 |
| } |
| |
| _Constraint:_ Methods can be defined *only* on types declared in the same package. |
| |
| // This won't compile |
| func (s string) Length() int { return len(s) } |
| |
| * Wait, pointers? |
| |
| Use `&` to obtain the address of a variable. |
| |
| a := "hello" |
| p := &a |
| |
| Use `*` to dereference the pointer. |
| |
| fmt.Print(*p + ", world") |
| |
| No pointer arithmetic, no pointers to unsafe memory. |
| |
| a := "hello" |
| p := &a |
| |
| p += 4 // no, you can't |
| |
| * Why pointers? |
| |
| Control what you pass to functions. |
| |
| - passing values, no side-effects: |
| |
| func double(x int) { |
| x *= 2 |
| } |
| |
| - passing pointers: side-effects possible: |
| |
| func double(x *int) { |
| *x *= 2 |
| } |
| |
| Control your memory layout. |
| |
| - compare []Person and []*Person |
| |
| * Method declarations on pointers |
| |
| Receivers behave like any other argument. |
| |
| Pointers allow modifying the pointed receiver: |
| |
| func (p *Person) IncAge() { |
| p.age++ |
| } |
| |
| The method receiver is a copy of a pointer (pointing to the same address). |
| |
| Method calls on nil receivers are perfectly valid (and useful!). |
| |
| func (p *Person) Name() string { |
| if p == nil { |
| return "anonymous" |
| } |
| return p.name |
| } |
| |
| * Interfaces |
| |
| * Interfaces |
| |
| An interface is a set of methods. |
| |
| In Java: |
| |
| interface Switch { |
| void open(); |
| void close(); |
| } |
| |
| In Go: |
| |
| type OpenCloser interface { |
| Open() |
| Close() |
| } |
| |
| * It's all about satisfaction |
| |
| Java interfaces are satisfied *explicitly*. |
| |
| Go interfaces are satisfied *implicitly*. |
| |
| .image //upload.wikimedia.org/wikipedia/commons/thumb/2/29/Rolling_Stones_09.jpg/512px-Rolling_Stones_09.jpg _ 512 |
| |
| .caption Picture by Gorupdebesanez [[http://creativecommons.org/licenses/by-sa/3.0][CC-BY-SA-3.0]], via [[http://commons.wikimedia.org/wiki/File%3ARolling_Stones_09.jpg][Wikimedia Commons]] |
| |
| * Go: implicit satisfaction |
| |
| _If_a_type_defines_all_the_methods_of_an_interface,_the_type_satisfies_that_interface._ |
| |
| Benefits: |
| |
| - fewer dependencies |
| - no type hierarchy |
| - organic composition |
| |
| * Structural subtyping |
| |
| Think static duck typing, verified at compile time. |
| |
| .image go4java/img/duck.jpg 500 500 |
| |
| * FuncDraw: an example on interfaces |
| |
| .image go4java/img/funcdraw.png 500 700 |
| |
| * FuncDraw: package parser |
| |
| Package `parse` provides a parser of strings into functions. |
| |
| func Parse(text string) (*Func, error) { ... } |
| |
| `Func` is a struct type, with an `Eval` method. |
| |
| type Func struct { ... } |
| |
| func (p *Func) Eval(x float64) float64 { ... } |
| |
| * FuncDraw: package draw |
| |
| Package draw generates images given a function. |
| |
| func Draw(f *parser.Func) image.Image { |
| for x := start; x < end; x += inc { |
| y := f.Eval(x) |
| ... |
| } |
| } |
| |
| `draw` depends on `parser` |
| |
| - makes testing hard |
| |
| Let's use an interface instead |
| |
| type Evaluable interface { |
| Eval(float64) float64 |
| } |
| |
| func Draw(f Evaluable) image.Image { ... } |
| |
| * Inheritance vs composition |
| |
| * Inheritance vs composition |
| |
| Lots of articles have been written about the topic. |
| |
| In general, composition is preferred to inheritance. |
| |
| Lets see why. |
| |
| * Runner |
| |
| .code go4java/BadInheritance.java /START_RUNNER/,/END_RUNNER/ |
| |
| * RunCounter is-a Runner that counts |
| |
| .code go4java/BadInheritance.java /START_COUNTING/,/END_COUNTING/ |
| |
| * Let's run and count |
| |
| What will this code print? |
| |
| .code go4java/BadInheritance.java /START_MAIN/,/END_MAIN/ |
| |
| Of course, this prints: |
| |
| running one |
| running two |
| running three |
| my runner ran 6 tasks |
| |
| Wait! How many? |
| |
| * My runner ran 6 tasks? Six? |
| |
| Inheritance causes: |
| |
| - weak encapsulation, |
| - tight coupling, |
| - surprising bugs. |
| |
| .image go4java/img/badinheritance.png |
| |
| * Solution: use composition |
| |
| .code go4java/Composition.java /START_COUNTING/,/BREAK_COUNTING/ |
| |
| * Solution: use composition (continued) |
| |
| .code go4java/Composition.java /BREAK_COUNTING/,/END_COUNTING/ |
| |
| * Solution: use composition (continued) |
| |
| *Pros* |
| |
| - The bug is gone! |
| - `Runner` is completely independent of `RunCounter`. |
| - The creation of the `Runner` can be delayed until (and if) needed. |
| |
| *Cons* |
| |
| - We need to explicitly define the `Runner` methods on `RunCounter`: |
| |
| public String getName() { return runner.getName(); } |
| |
| - This can cause lots of repetition, and eventually bugs. |
| |
| * There's no inheritance in Go |
| |
| * There's no inheritance in Go |
| |
| Let's use composition directly: |
| |
| # .code go4java/runner/runner.go /type Task/,/END_TASK/ |
| |
| .code go4java/runner/runner.go /type Runner/,/END_RUNNER/ |
| |
| All very similar to the Java version. |
| |
| * RunCounter |
| |
| `RunCounter` has a `Runner` field. |
| |
| .code go4java/runner/runner.go /type RunCounter/, |
| |
| * Composition in Go |
| |
| Same pros and cons as the composition version in Java. |
| |
| We also have the boilerplate to proxy methods from `Runner`. |
| |
| .code go4java/runner/runner.go /runner.Name/ |
| |
| But we can remove it! |
| |
| * Struct embedding |
| |
| Expressed in Go as unnamed fields in a struct. |
| |
| It is still *composition*. |
| |
| The fields and methods of the embedded type are defined on the embedding type. |
| |
| Similar to inheritance, but the embedded type doesn't know it's embedded. |
| |
| * Example of struct embedding |
| |
| Given a type `Person`: |
| |
| .code go4java/embedsample.go /Person/,/Hi/ |
| |
| We can define a type `Employee` embedding `Person`: |
| |
| .code go4java/embedsample.go /Employee/,/}/ |
| |
| All fields and methods from `Person` are available on `Employee`: |
| |
| .code go4java/embedsample.go /var/,/Introduce/ |
| |
| * Struct embedding |
| |
| .code go4java/runner/embed.go /type RunCounter2/, |
| |
| * Is struct embedding like inheritance? |
| |
| No, it is better! |
| |
| It is composition. |
| |
| - You can't reach into another type and change the way it works. |
| |
| - Method dispatching is explicit. |
| |
| It is more general. |
| |
| - Struct embedding of interfaces. |
| |
| * Is struct embedding like inheritance? |
| |
| Struct embedding is selective. |
| |
| .code go4java/writecounter.go /WriteCounter/,/MAIN/ |
| |
| WriteCounter can be used with any `io.ReadWriter`. |
| |
| .play go4java/writecounter.go /func main/,/^}/ |
| |
| * Easy mocking |
| |
| What if we wanted to fake a part of a `net.Conn`? |
| |
| type Conn interface { |
| Read(b []byte) (n int, err error) |
| Write(b []byte) (n int, err error) |
| Close() error |
| LocalAddr() Addr |
| RemoteAddr() Addr |
| SetDeadline(t time.Time) error |
| SetReadDeadline(t time.Time) error |
| SetWriteDeadline(t time.Time) error |
| } |
| |
| I want to test `handleCon`: |
| |
| .code go4java/loopback.go /handleCon/ |
| |
| - We could create a `fakeConn` and define all the methods of `Conn` on it. |
| |
| - But that's a lot of boring code. |
| |
| * Struct embedding of interfaces |
| |
| _WARNING_:_Cool_stuff_ |
| |
| If a type T has an embedded field of a type E, all the methods of E will be defined on T. |
| |
| Therefore, if E is an interface T satisfies E. |
| |
| * Struct embedding of interfaces (continued) |
| |
| We can test `handleCon` with the `loopBack` type. |
| |
| .code go4java/loopback.go /loopBack/,/^}/ |
| |
| Any calls to the methods of `net.Conn` will fail, since the field is nil. |
| |
| We redefine the operations we support: |
| |
| .code go4java/loopback.go /Read/, |
| |
| * Concurrency |
| |
| * Concurrency |
| |
| It is part of the language, not a library. |
| |
| Based on two concepts: |
| |
| - goroutines: lightweight threads |
| - channels: typed pipes used to communicate and synchronize between goroutines |
| |
| So cheap you can use them whenever you want. |
| |
| .image go4java/img/funnelin.jpg 300 700 |
| |
| * Sleep and talk |
| |
| .code go4java/conc1.go /sleepAndTalk/,/^}/ |
| |
| We want a message per second. |
| |
| .play go4java/conc1.go /func main/,/^}/ |
| |
| What if we started all the `sleepAndTalk` concurrently? |
| |
| Just add `go`! |
| |
| * Concurrent sleep and talk |
| |
| .play go4java/conc2.go /func main/,/^}/ |
| |
| That was fast ... |
| |
| When the `main` goroutine ends, the program ends. |
| |
| * Concurrent sleep and talk with more sleeping |
| |
| .play go4java/conc3.go /func main/,/^}/ |
| |
| But synchronizing with `Sleep` is a bad idea. |
| |
| * Communicating through channels |
| |
| `sleepAndTalk` sends the string into the channel instead of printing it. |
| |
| .code go4java/chan.go /sleepAndTalk/,/^}/ |
| |
| We create the channel and pass it to `sleepAndTalk`, then wait for the values to be sent. |
| |
| .play go4java/chan.go /func main/,/^}/ |
| |
| * Let's count on the web |
| |
| We receive the next id from a channel. |
| |
| .code go4java/goodcounter.go /nextID/,/^}/ |
| |
| We need a goroutine sending ids into the channel. |
| |
| .play go4java/goodcounter.go /func main/,/^}/ |
| |
| [[http://localhost:8080/next]] |
| |
| * Let's fight! |
| |
| `select` allows us to chose among multiple channel operations. |
| |
| .play go4java/battle.go /battle/,/^}/ |
| |
| Go - [[http://localhost:8080/fight?usr=go]] |
| Java - [[http://localhost:8080/fight?usr=java]] |
| |
| * Chain of gophers |
| |
| .image go4java/img/chain.jpg |
| |
| Ok, I'm just bragging here |
| |
| * Chain of gophers |
| |
| .play go4java/goroutines.go /func f/, |
| |
| * Concurrency is very powerful |
| |
| And there's lots to learn! |
| |
| - [[http://go.dev/talks/2012/concurrency.slide#1][Go Concurrency Patterns]], by Rob Pike |
| - [[http://go.dev/talks/2013/advconc.slide#1][Advanced Concurrency Patterns]], by Sameer Ajmani |
| - [[http://go.dev/talks/2012/waza.slide#1][Concurrency is not Parallelism]], by Rob Pike |
| |
| .image go4java/img/busy.jpg |
| |
| * In conclusion |
| |
| Go is simple, consistent, readable, and fun. |
| |
| All types are equal |
| |
| - methods on any type |
| |
| Implicit interfaces |
| |
| - Structural typing |
| - Less dependencies |
| - Code testable and reusable |
| |
| Use composition instead of inheritance |
| |
| - Struct embedding to remove boilerplate. |
| - Struct embedding of interfaces to satisfy them fast. |
| |
| Concurrency is awesome, and you should check it out. |
| |
| * What to do next? |
| |
| Learn Go on your browser with [[http://tour.golang.org][tour.golang.org]] |
| |
| Find more about Go on [[http://golang.org][golang.org]] |
| |
| Join the community at [[https://groups.google.com/forum/#!forum/Golang-nuts][golang-nuts]] |
| |
| Link to the slides [[http://go.dev/talks/2014/go4java.slide]] |