Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go for Java Developers @ Java User Group Saarland

Go for Java Developers @ Java User Group Saarland

Diesmal wollen wir wieder einen Blick über den Tellerrand wagen und uns einer Programmiersprache abseits von JVM & Co zuwenden die insbesondere im Kontext von Cloud
Native Architekturen stark verbreitet ist: Die Programmiersprache Go.

/Abstract
Go ist eine einfache, typsichere Programmiersprache,
die 2009 von Google Open-Sourced wurde. Go kompiliert direkt zu
ausführbaren Dateien, hat eine eingebaute Garbage-Collection und bringt Unterstützung für Multi-Threading mit.
Besonders bei systemnahen, verteilten Anwendungen erfreut sich Go stetig wachsender Beliebtheit.
Einige Beispiele für erfolgreiche Go-Projekte sind Docker, Kubernetes und Prometheus-Monitoring, sowie zahlreiche kleinere Command-line Tools.

Dieser Vortrag bietet einen Überblick zur Programmiersprache Go und stellt
zentrale Konzepte wie Channels, Functional Programming und Tooling für Build und Testen vor.

/Bio
Thomas arbeitet als Software Architekt bei der eurodata AG und war zuvor Spring Data Engineer im Spring Team bei Pivotal. Er beschäftigt sich bereits seit mehreren Monaten privat mit der Programmiersprache Go.

Thomas Darimont

February 27, 2018
Tweet

More Decks by Thomas Darimont

Other Decks in Programming

Transcript

  1. Java User Group Saarland Go for Java Developers Thomas Darimont

    eurodata AG 35. Meeting 27. February 2018 Sponsored by
  2. What is Go? • Open Source Programming Language created by

    Google in 2007 ◦ Robert Griesemer, Rob Pike, and Ken Thompson ◦ Unix, C, UTF-8, Plan 9 ◦ Current Version 1.10 • Main design goal ◦ Focus on simplicity - not many features ◦ Philosophy: “Less is exponentially more” • Main purpose ◦ Initially: System tools programming ◦ Nowadays: CLI & Backend Applications • Language of the Cloud ◦ Highly performant and scalable ◦ Efficient ◦ Built-in concurrency support ◦ Easy to read and to maintain ◦ Support for multiple OS 3
  3. Why learn Go? • Learning a new Programming Languages makes

    you a better programmer ◦ Go maybe a better choice than Java in certain situations • Contribute or integrate with existing Go Projects ◦ Kubernetes, Docker, Cloud Foundry,... • Increasing demand for developers proficient in Go • Companies that use Go ◦ Google, Dropbox, Pivotal, Microsoft, Sixt, Facebook, Twitter ◦ https://github.com/golang/go/wiki/GoUsers 4
  4. Go and Java Similarities • Fast ◦ Almost as fast

    as C ◦ Faster than C in some cases • C-style • Imperative • Compiled • Statically typed • Object-oriented • Cross-platform • Garbage collection • Memory safety • Type assertions • Reflection • Packages and Imports 5
  5. Go and Java Differences • No VM ◦ Programs are

    compiled ahead of time to native machine code ◦ Executed on the processor directly • Small language • Syntax differences • Built-in strings, arrays and maps • Type inference • “real” Closures • Concurrency via CSP (Communicating Sequential Processes) • No Classes • No Inheritance, no type hierarchy • No Annotations • No Generics • No Overloaded Methods 6
  6. Why is Go so different? • “Language design in the

    service of software engineering” • Familiar, yet modern • High performance, compiler and runtime • Balance between complexity and convenience • Emphasis on automated tools 7
  7. Runtime • Compiled into every executable go program ◦ Runtime

    ~ 1MB ◦ No other dependencies required, e.g. no libc ◦ Single executable binary, allows small Docker images • Garbage Collection • Concurrency • Stack Management • Extensive library ◦ “Batteries included” ◦ Go’s runtime is analogous to libc, the C library 8
  8. Hello World! package main import "fmt" func main() { fmt.Println("Hello,

    JUGSaar") } 9 $ go run hello_world.go Hello, JUGSaar
  9. Keywords 10 break func select case go struct chan goto

    switch const if type continue import var default interface defer map else package fallthrough range for return Java 1.8 (42*) Go 1.10 (25*) abstract else instanceof strictfp assert enum interface super break extends native switch case final new synchronized catch finally package this class for private throw const goto protected throws continue if public transient default implements return try do import static void volatile while *) Without built-in types
  10. Using Package package main import ( "fmt" "math/rand" ) func

    main() { fmt.Println("My favorite number is: ", rand.Int(10)) } 11 One can also import packages with separate lines import "fmt" import "math/rand"
  11. Exported Names acme.PrintSomething("hello") // exported 12 • In Go, a

    symbol is exported if it begins with a capital letter. acme.printSomethingElse("world") // not exported • Use... • Instead of
  12. Variables package main import "fmt" var x, y, z int

    func main() { var c, python, java = true, false, "no!" haskell, clojure, sml := true, true, true fmt.Println(x,y,z,c,python, java, haskell, clojure, sml) } 13 using := construct, we can omit var keyword and type! “short-form” type can be omitted, since compiler can guess it from the value expression
  13. Basic Data Types • Go has a set of basic

    types and pointers ◦ byte, int (signed, unsigned), float ◦ bool ◦ rune represents Unicode codepoint ◦ string ◦ complex support for complex numbers • Go has also Pointers, but no pointer arithmetic ◦ Pointers in Go are treated similar to references in Java ◦ Purpose: Pass large data sets efficiently around ◦ uintptr ▪ integer type large enough to hold any pointer ◦ var p *string = &s ▪ * denotes a pointer type, C-style dereferencing ▪ & C-style “address-of” operator 14 Go type Java Type int8 / byte byte int16 short int32 (int/rune) int int64 long float32 float float64 double Numeric Types in Go and Java
  14. Constants package main import "fmt" const Pi = 3.0 func

    main() { const World = "世界" fmt.Println("Hello", World) fmt.Println("Happy", Pi, "Day") const Truth = true fmt.Println("Go rules?", Truth) } 15
  15. Grouping Variables and Constants import "math/cmplx" var ( ToBe bool

    = false MaxInt uint64 = 1<<64 - 1 z complex128 = cmplx.Sqrt(-5 + 12i) ) const ( Big = 1 << 100 Small = Big >> 99 ) 16
  16. Functions package main import "fmt" func add(x int, y int)

    int { return x + y } func add_and_sub(x, y int) (int, int) { return x + y, x - y } func main() { fmt.Println(add(42, 13)) a, b := add_and_sub(42, 13) fmt.Println(a, b) } 17 parameter name type return type parameter name type multiple return types receiving multiple return values
  17. Functions - Named results package main import "fmt" func split(sum

    int) (x, y int) { x = sum * 4/9 y = sum - x return } func main() { fmt.Println(split(17)) } 18
  18. Error Handling • Functions declare second return value of type

    error (error is an interface) ◦ If error happened, then return default value and error ◦ If no error happened, then return actual value and nil as error • Go has no Exceptions so error handling happens by checking for errors • Syntax for Checking for errors is a bit awkward… 19 func f() (int, error) { … if errorHappened { return 0, fmt.Errorf(“...”) } … return 1, nil } n, err := f() if err != nil [ … handle error return } // can safely use n
  19. Functions - First Class Citizens func main() { hypot :=

    func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } fmt.Println(hypot(3,4)) } 20 Creates a anonymous (lambda) function and assign it to a variable Functions in Go are first class citizens, which means that you can pass them around like values.
  20. Closures func fibonacci() func() int { x, y := 0,

    1 return func() int { x, y = x+y, x return x } } func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } } 21 Go uses lexical closures, which means a function is evaluated in the environment where it is defined. x and y are accessible inside the anonymous function!
  21. For loop func main() { sum := 0 for i

    := 0; i < 10; i++ { sum += i } for ;sum < 1000; { sum += sum } for sum < 10000 { sum += sum } fmt.Println(sum) for { fmt.Println("4ever") } } 22 similar to Java but without parentheses Go does not have a while loop! While loops are for loops! Infinite loop!
  22. Conditionals: If package main import "fmt" func main() { a

    := 10 if a > 1 { fmt.Println("if true") } if b := 123 * 456; b < 10000 { fmt.Println("another one, but with short statement") } } 23 short statement, b is only visible inside if block!
  23. Conditionals: Switch import "fmt" import "runtime" func main() { fmt.Print("Go

    runs on ") switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: fmt.Printf("%s.", os) } } 24 Just like if, you can use the short form here Switch cases evaluate from top to bottom, stopping when a case succeeds. No automatic fall-through! → Fall-through via fallthrough keyword
  24. Switch Without Condition import "fmt" import "runtime" t := time.Now()

    switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } 25 no condition Like writing long if/else chains
  25. Structs package main import "fmt" type Vertex struct { X

    int Y int } func main() { v := Vertex{1,2 } v.X = 4 fmt.Println(v) } 26 A struct is a collection of fields. Struct fields are accessed using a dot. Go’s mechanism for composing types
  26. Structs package main import "fmt" type Vertex struct { X

    int Y int } func main() { v := Vertex{1,2 } v.X = 4 p := &v fmt.Println(v.X, p.X) } 27 p has a pointer to v, which has type *Vertex Use dot to access field of a pointer
  27. The new Function package main import "fmt" type Vertex struct

    { X,Y int } func main() { v := new(Vertex) fmt.Println(v) v.X, v.Y = 11, 9 fmt.Println(v) } 28 The expression new(T) allocates a zeroed T value and returns a pointer to it. v has type:; *Vertex
  28. Arrays VS. Slices • Arrays have a fixed length and

    are mutable ◦ Syntax [length]type, c.f. [2]string ◦ Similar to typed arrays in Java, c.f. int[] ◦ Length of arrays is part of the type … makes it less useful ◦ Examples ▪ a := [2]string{"aaa","bbb"} ▪ languages := [...]string{"german", "english", "french"} // size determined by elements • Slices are dynamically sized and mutable ◦ Syntax []type, c.f. []string ◦ Similar to ArrayList in Java ◦ can be grown dynamically ▪ s := make([]string, 3) ▪ s = append(s, "a", "b", "c", "d") ◦ Examples ▪ s := []string{} ▪ s := []string{"aaa", "bbb"} // slice literal 29
  29. Slices package main import "fmt" func main() { p :=

    []int{2, 3, 5, 7, 11, 13} // slice literal fmt.Println("p == ", p) fmt.Println("p == ", p[1:4]) // [3 5 7] fmt.Println("p == ", p[:3]) // [2 3 5] fmt.Println("p == ", p[4:]) // [11 13] for i := 0; i < len(p); i++ { fmt.Printf("p[%d] == %d\n", i, p[i]) } } 30 A slice points to an array of values and also includes a length. The zero value of a slice is nil
  30. Maps package main import "fmt" type Vertex struct { Lat,

    Long float64 } func main() { m := make(map[string]Vertex) m["Bell Labs"] = Vertex{40.68433, -74.39967} fmt.Println(m["Bell Labs"]) } 31 A map maps keys to values. Maps can be created with make (not new) before use; the nil map is empty and cannot be assigned to.
  31. Map Literals package main import "fmt" type Vertex struct {

    Lat, Long float64 } func main() { m := map[string]Vertex { "Bell Labs": Vertex{40.68433, -74.39967}, } fmt.Println(m["Bell Labs"]) } 32 trailing comma!
  32. Mutating Maps m := map[string]Vertex { "Bell Labs": Vertex{40.68433, -74.39967},

    } // Add element m["Google"] = Vertex{40.68533, -74.3367} // Test if Key exists n, ok := m["Intel"] if ok { fmt.Println("key exists!") } // Delete an item delete(m, "Google") 33
  33. Iterating through Slices or Maps package main import "fmt" func

    main() { nums := []int{2, 3, 5, 7, 11, 13} for i, v := range nums { fmt.Println(i, v) } for _, v := range nums { fmt.Println(v) } } 34 Go provides the range keyword for iteration. Works for slices, arrays, maps and channels. _ ignored value
  34. • Methods are functions attached to a type • It

    is possible to attach a method to any type - including library types • Receiver can be named arbitrarily - in Java the receiver is always called this • Syntax func (RECEIVER) Name(Args) RETURN_TYPE { … } Methods 36 https://play.golang.org/p/UDuOv2loKJj type Stack struct { data []string } func (s *Stack) Push(x string) { s.data = append(s.data, x) } func main() { s := &Stack{} // creates new “instance” of Stack s.Push("Hello") s.Push("World") fmt.Println(s) // prints [Hello World] }
  35. Method Declaration type Vertex struct { X, Y float64 }

    func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { v := &Vertex{3, 4} fmt.Println(v.Abs()) } 37 Methods basically look like functions, but with extra receiver declaration before function name.
  36. Type embedding import "time" import "fmt" type MyTime struct {

    time.Time // struct embedding } func (t MyTime) bla() string { return t.Local().String()[0:20] } func main() { mt := &MyTime{} fmt.Println(mt.bla()) } 38 Sort of “Inheritance”...
  37. Defer • Useful construct related to error handling • similar

    to try{ … } finally {...} in Java • Syntax defer callableExpression(argExpressions) ◦ argExpressions are evaluated immediately ◦ callableExpression is evaluated on block / function exit 39 resp, err := http.Get(url) if err != nil { ... } defer resp.Body.Close() … // resp.Body.Close() invoked before block exit
  38. Interfaces • Very similar to interfaces in Java but more

    flexible ◦ There is no “implements” in Go • Structural typing ◦ A type “implements” / satisfies an interface by declaring matching method signatures ◦ Makes it easy to work with libraries 40 func Fprintf(w io.Writer, format string, args ...interface {}) (int, error) { ... } type Writer interface { Write(p []byte) (int, error) } type NopWriter struct { } func (w *NopWriter) Write(p []byte) (int, error) { return len(p), nil } var w NopWriter fmt.Fprintf(&w, “Hello, World!”)
  39. Concurrency • Go uses a CSP model (Communicating Sequential Processes)

    ◦ State is passed as messages through Channels between concurrent processes ◦ Go Proverb: Don’t communicate by sharing memory, share memory by communicating • Unit of execution is a Go Routine ◦ Scheduled by the Go Runtime on a M-N threading model ◦ Similar to Green Threads in former Java versions ◦ Context switching is very cheap • Go Routines are started via the go keyword ◦ Every function can be executed in a Go Routine 41 func say(s string) { fmt.Println(s) } go say(“hi”) say(“there”)
  40. Channels • Can be uni-directional (r or w) or bidirectional

    (rw) • Send / Receive Operations are blocking … unless the channel is configured with a buffer. • So somebody on the other side must receive / accept the value before you can continue. ◦ Makes channels a good synchronization mechanism 42 https://play.golang.org/p/3Boc_djIBVE ch := make (chan int) // create channel ch <- x //send x = <- ch //receive and assign <-ch // receive and discard close (ch) // closes the channel
  41. Select • Select will execute whatever which blocking operation is

    ready to receive… ◦ can also wait for timeout and do something else… 43 https://play.golang.org/p/E4RMck62dWf select { case <- ch1: // receive … case x:= <- ch2: // receive and assign … default: ... }
  42. Tools • go ◦ Think of java, javac, maven +

    gradle in one tool • go run • go build • go install • go test • go get • go vet • gofmt • goimports • godep (dep) 44
  43. Conclusion • Go is similar to Java yet very different

    • Go is simple, elegant, and efficient • Go is worth giving a try 46
  44. Links • Code & Slides https://github.com/jugsaar/jugsaar-35-go4java-developers • Website https://golang.org •

    Playground https://play.golang.org • Language Specification https://golang.org/ref/spec • GoTime FM Podcast https://changelog.com/gotime 47