KEMBAR78
Golang basics for Java developers - Part 1 | PPTX
Golang basics…
...for Java developers
Robert Stern
Agenda
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Java vs. Go
All you need is…
https://play.golang.org/
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
History and features
Created in 2007 at Google, announced in 2009, v1.0 released in 2012) with strong
dedication for server side programming.
Compiled, statically typed, garbage collected language with multiple
architecture/OS support (i386, amd64, arm/Windows, Linux, *BSD, etc..)
(very) fast compilation AND execution time with low resource consumption
Powerful cli (go get, go build, go test, go install…)
Current stable version is 1.6.3 and still being actively developed
What is missing or disturbing?
No generics
Not an OO language
No constructors
No operator/method overloading
No circular package imports
No mandatory semicolons
GC pause is unpredictable
What is non-java-isch?
Multiple return values + the blank variable
Golang is a pass-by-value language
Lightweight concurrency with goroutines and channels
No SE/EE separation. All server stuff is built-in.
No exceptions, use error instead
Compile time error about unused imports and variables
No maven/ant like build system. Uses Makefile+vendoring+go get
Famous projects, companies
Projects:
App Engine with Go, AWS with Go SDK, Docker, Kubernetes, Grafana, Terraform,
Gogs (Go Git Service), etcd, drone.io, Syncthing, CockroachDB, rkt, nsq, consul,
boltDB, weave, swarm, vulcand, gryffin, fleet, minio…
Companies:
Google (of course…), Netflix, Dropbox, CloudFlare, SoundCloud, BBC, Uber,
Couchbase, MongoDB...
Google trends - golang
A bit bigger picture about the trends
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
Hello world in golang:
package main
// imports
import "fmt"
/*
This is the main function
*/
func main() {
fmt.Println("Hello, World!")
}
Try it in the Go playground!
Hello world
Go project structure
❏ Workspace ($GOPATH or %GOPATH%)
❏ src/pkg/bin roots
❏ Repository (github.com, etc…)
❏ Package
❏ Go source files
Structure example
Packages
Like in Java, golang also uses packages to organize code, but in a bit different
format.
Keyword: package <name>
The app starts in the main package.
the path to the package’s directory is the import path
The package name is the last element of the import path:
github.com/zooplus/golang-app/stringutil → stringutil
Accessing stringutil functions/elements: stringutil.<name>
import (
"reflect"
"strings"
"github.com/emicklei/go-restful"
)
import "reflect"
import "strings"
import "github.com/emicklei/go-restful"
Importing packages
Package types
To use one or more functions in a package we need to import it into our code. We
can import system, local and remote packages.
System packages are the golang out of box packages like http, testing, etc..
Local package resides in your repository, no full path needed
Remote packages has complete import path pointing to the server like:
github.com/emicklei/go-restful
Getting the dependencies
For remote packages use go get to fetch into your workspace. We have two
syntaxes
go get in the repository folder downloads all remote packages based on the
imports
go get <remote path> downloads the specified package for later use
Variables, constants
package main
import "fmt"
const greeting = "Hello"
var name string
func main() {
name = "Zooplus"
space := " "
fmt.Println(greeting + space + name)
}
if _, err := os.Stat(path); os.IsNotExist(err) {
fmt.Printf("%s does not existn", path)
}
The blank identifier
“The blank identifier can be assigned or declared with any value of any type, with the value
discarded harmlessly”
(https://golang.org/doc/effective_go.html#blank)
Exported names
“In Go, a name is exported if it begins with a capital letter.
For example, Pizza is an exported name, as is Pi, which is exported from the math package.”
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.pi)
}
Practice!
Refactor the greeting app to use fmt.Printf(format, args...)** and display the following message:
Hello Zooplus, today is Friday.
The name of the day as string can be printed with:
import "time"
...
time.Now().Format("Monday")
**(Use %s for string)
A solution
package main
import (
"fmt"
"time"
)
func main() {
name := "Zooplus"
fmt.Printf("Hello %s, today is %s.", name, time.Now().Format("Monday"))
}
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
Basic types
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32, represents a Unicode code point
float32 float64
complex64 complex128 - “math/cmplx”:
var number complex128 = cmplx.Sqrt(-5 + 12i)
Pointers - bit.ly/2a58jnI
package main
import "fmt"
func main() {
i, j := 42, 2701
p := &i // point to i
fmt.Println(*p) // read i through the pointer
*p = 21 // set i through the pointer
fmt.Println(i) // see the new value of i
p = &j // point to j
*p = *p / 37 // divide j through the pointer
fmt.Println(j) // see the new value of j
}
package main
var (
a int
b int32
c int16
)
func main() {
a = 1
b = a
c = a
}
No autoboxing! You should convert your types by yourself.
package main
import "fmt"
var (
a int
b int32
c int16
)
func main() {
a = 1
b = int32(a)
c = int16(a)
fmt.Printf("a: %d, b: %d, c: %d", a, b, c)
}
Type conversion
prog.go:11: cannot use a (type int) as type int32 in assignment
prog.go:12: cannot use a (type int) as type int16 in assignmenta: 1, b: 1, c: 1
Struct
type ApacheLogRecord struct {
ip
string
time
string
method, uri, protocol
string
status int
responseBytes int
referer
string
userAgent
string
}
1. result = &ApacheLogRecord{
ip: nvl(req.RemoteAddr),
time: timeFormatted,
method: nvl(req.Method),
uri: nvl(req.URL.Path),
protocol: nvl(req.Proto),
status: resp.StatusCode(),
responseBytes:
resp.ContentLength(),
referer: nvl(req.Referer()),
userAgent:
nvl(req.UserAgent()),
}
2.) result = new(ApacheLogRecord)
package main
import "fmt"
type Animal struct {
legCount int
}
// define a behavior for Animal
func (a Animal) numberOfLegs() int {
return a.legCount
}
type Dog struct {
Animal //anonymous field Animal
}
func main() {
d := Dog{Animal{4}}
//no method defined for Dog, but we have the same behavior as Animal.
fmt.Println("A Dog has this many legs: ", d.numberOfLegs())
}
Embedding, inheritance -bit.ly/2axY1yu
Receiver methods -bit.ly/2a56VkS
package main
import "fmt"
type Animal struct {
legCount int
}
func (a Animal) numberOfLegs() int {
return a.legCount
}
func (a Animal) setLegs(c int) {
a.legCount = c
}
type Mammal struct {
weight int
}
func (m Mammal) getWeight() int {
return m.weight
}
func (m Mammal) setWeight(w int) {
m.weight = w
}
type Dog struct {
Animal
Mammal
}
func main() {
d := Dog{Animal{4}, Mammal{10}}
fmt.Printf("A Dog has this many legs: %d oh... and weight: %d", d.numberOfLegs(), d.getWeight())
}
Pointer receivers -bit.ly/2aKK7si
package main
import "fmt"
type Animal struct {
legCount int
}
func (a Animal) numberOfLegs() int {
return a.legCount
}
func (a Animal) setLegs(c int) {
a.legCount = c
}
func (a *Animal) setLegsPtr(c int) {
a.legCount = c
}
type Dog struct {
Animal //anonymous field Animal
}
func main() {
d := Dog{Animal{4}}
fmt.Println("A Dog has this many legs: ", d.numberOfLegs())
d.setLegs(5)
fmt.Println("A Dog has this many legs: ", d.numberOfLegs())
d.setLegsPtr(6)
fmt.Println("A Dog has this many legs: ", d.numberOfLegs())
}
Arrays -bit.ly/2ahx5EA
Arrays has fix size and type with zero based indexing:
var integers [20]int
package main
import "fmt"
func main() {
var a [2]string // std declaration
a[0] = "Hello"
a[1] = "Zooplus"
fmt.Println(a[0], a[1])
fmt.Println(a)
fibonacci := [6]int{1, 1, 2, 3, 5, 7} // on-the-fly declaration
fmt.Println(fibonacci)
}
Slices - bit.ly/2ahVarP
Slice is a dynamic version of array (a sort of):
var integers []int // decleration of a slice without size
package main
import "fmt"
func main() {
fibonacci := [6]int{1, 1, 2, 3, 5, 7}
var p []int = fibonacci[1:4]
fmt.Println(p)
}
Slices are not storing data - bit.ly/2aai1Wx
package main
import "fmt"
func main() {
names := [4]string{
"John",
"Paul",
"George",
"Ringo",
}
fmt.Println(names)
a := names[0:2]
b := names[1:3]
fmt.Println(a, b)
b[0] = "XXX"
fmt.Println(a, b)
fmt.Println(names)
}
Slices - bounds
There are default low and high bounds for slices. Given the following array:
var a [10]int
The following slice declarations are equivalent:
a[0:10]
a[:10]
a[0:]
a[:]
Creating slice:
a := make([]int, 5) // len(a)=5
Creating slice with capacity:
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
Appending slice:
b = append(b, 10)
Further reading: https://blog.golang.org/go-slices-usage-and-internals
Slices - create, append
Arrays, slices - for loop as foreach
Iterate through an array/slice
for index, value := range arr {
fmt.Println("Index:", index, "Value:", value)
}
Get the index only:
for index := range arr {
fmt.Println("Index:", index)
}
Get the values:
for _, value := range arr {
fmt.Println("Value:", value)
}
Maps - declaration, initialization
Maps are not initialized by default, we should use make:
package main
import "fmt"
var m map[string]string
func main() {
m = make(map[string]string)
m["Zooplus"] = "Gut"
m["Bitiba"] = "Gut"
m["Fressnapf"] = "Falsch"
fmt.Println(m["Zooplus"])
}
Maps - Mutating maps
m[key] = item // upsert
item = m[key] // retrieve
delete (m, key) // guess….
_, ok = m[key] // ok == true if key exists, map can store/return nil
Maps are not thread safe!!!
Maps - for loop as foreach
Iterate through a map:
for key, value := range m {
fmt.Println("Key:", key, "Value:", value)
}
Get the keys:
for key := range m {
fmt.Println("Key:", key)
}
Get the values:
for _, value := range m {
fmt.Println("Value:", value)
}
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
The one and only: for loop
// normal loop
sum := 0
// init-condition-post
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
// partial loop
sum := 0
// init and post are optional
for ; sum < 10; {
sum += sum
}
// “while” loop
sum := 1
// init and post are optional
for sum < 1000 {
sum += sum
}
fmt.Println(sum)
// infinite loop
for {
}
func GetProject(req *restful.Request, resp *restful.Response) {
resp.Header().Set("Pragma", "no-cache")
//
pId := req.PathParameter("projectId")
if project, ok := projects.GetProjectByIdOrName(pId); ok
{
ReturnJSON(resp, http.StatusOK, project)
}
ReturnMessage(resp, http.StatusNotFound, "Project not
found!")
}
If-then-else
existingPipeline, ok := nameSpace.Pipelines[newPipeline.Name]
if ok {
log.Debug("Entry exists!")
} else {
nameSpace.Pipelines[newPipeline.Name] = existingPipeline
log.Debug("New entry stored")
}
?
Switch
Switch in Golang is a bit different from Java:
No automatic fallthrough, no need to put break at the end in every cases
You can delegate expression evaluation into the case block
fallthrough keyword for java-ish behavior
Multiple conditions in one case (no empty cases like in java)
Not limited to string and int
Type switch can be used for interface{} to find out the real type (instanceof)
Switch - no fallthrough by default
switch c {
case '&':
esc = "&amp;"
case ''':
esc = "&apos;"
case '<':
esc = "&lt;"
case '>':
esc = "&gt;"
case '"':
esc = "&quot;"
default:
panic("unrecognized escape character")
}
Switch - strings are welcome
switch syscall.OS {
case "windows":
...
case "plan9":
...
default:
...
}
Switch - (multiple)expression(s) in cases
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
switch chars[code].category {
case "de", "uk", "fr", "sp", "nl":
return true
}
Switch - Type switch
switch v.(type) {
case int:
return "int"
case string:
return "string"
default:
return "unknown"
}
Switch - you can break it
switch argv[0] {
case "echo":
fmt.Print(argv[1:]...)
case "cat":
if len(argv) <= 1 {
fmt.Println("Usage: cat <filename>")
break
}
PrintFile(argv[1])
default:
fmt.Println("Unknown command; try 'echo' or 'cat'")
}
Switch - fallthrough
switch len(src) {
default:
v |= uint32(src[3])
fallthrough
case 3:
v |= uint32(src[2]) << 8
fallthrough
case 2:
v |= uint32(src[1]) << 16
fallthrough
case 1:
v |= uint32(src[0]) << 24
}
Errors instead of exceptions
Golang has no exceptions
and of course there are no checked exceptions :)))))))
No try-catch-finally.
Error is just an interface
Functions are often returning a value and an error together.
Checking this error for nil is the exception handling in Golang:
// validate
pipeline, err := validateYaml(buf.Bytes())
if err != nil {
errorMessage := fmt.Sprintf("Error parsing pipeline config: %s", err)
log.Error(errorMessage)
http.Error(w, errorMessage, http.StatusBadRequest)
} else {...}
NO CHECKED EXCEPTIONS!!!
Defer
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
defer fmt.Println(“All closed”)
return io.Copy(dst, src)
}
Panic and Recover -bit.ly/2a5m0mJ
func main() {
f()
fmt.Println("Returned normally from f.")
}
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i + 1)
}
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
Functions -bit.ly/2a5mg4W
package main
import "fmt"
func swap(x, y string) (string, string) { // also can use (x string, y string)
return y, x
}
func main() {
a, b := swap("hello", "zooplus")
fmt.Println(a, b)
}
Functions -bit.ly/2aymMe6
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))
}
Interfaces
Golang has no “implements” keyword. If you implement all methods defined by the
interface, then you are implemented the interface implicitly.
package main
import "fmt"
type I interface {
M()
}
type T struct {
S string
}
// This method means type T implements the interface I,
// but we don't need to explicitly declare that it does so.
func (t T) M() {
fmt.Println(t.S)
}
func main() {
var i I = T{"hello"}
i.M()
}
The empty interface - bit.ly/2awwq3Z
Like Object in Java, Golang has the interface{} as type that compatible with every
value (even with primitives).
So it can hold any value. You need type assertion to find out what is it:
package main
import "fmt"
func main() {
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
s, ok := i.(string)
fmt.Println(s, ok)
f, ok := i.(float64)
fmt.Println(f, ok)
f = i.(float64) // panic
fmt.Println(f)
}
Reflection
“In computer science, reflection is the ability of a computer program to examine
and modify its own structure and behavior (specifically the values, meta-data,
properties and functions) at runtime.” /Wikipedia/
Golang has a reflection package to inspect structs, interfaces or methods runtime
like in Java and also you can change the values of the fields.
What you’ll miss is some bytecode manipulation and proxy generation. Mockito
like framework is not possible in Golang.
See more: http://blog.ralch.com/tutorial/golang-reflection/
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
Similarities with Java
Goroutine = Thread
Locks (R, RW)
Atomic package thread safe variable handling
Waitgroup = Join
Differences from Java
Goroutine is lightweight, but not reusable
No Threadlocal or Executorservice in Golang
Golang has no thread safe map implementation by default
(https://github.com/streamrail/concurrent-map)
Golang is a pass-by-value language
Golang uses channels to communicate between threads
Golang unsafe package is more limited
To summarize: Java originally built-on the shared memory concept, but the
Golang is focusing on the communication with channels
Channels
ch := make(chan int) // single item channel
v:= 5
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
ch := make(chan int,100) // buffered channel
v:= 5
ch <- v // Send v to channel ch.
v := <-ch // Receive from ch, and
// assign value to v.
Looping on a channel
package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
Overview
Basic syntax and structure
Datatypes
Flow control
Functions, interfaces
Concurrency
Java vs. Go
Go and Java common points
C like (braces)
Garbage collector
Memory safety (nil/null references, runtime bounds checks)
Statically typed
Variables initialized by default(zero/nil/false)
Methods, Interfaces
Go and Java differences
Native code without VM + statically linked binaries
Control over memory layout
Function values and lexical closures
Built-in strings (UTF-8)
Built-in generic maps and arrays/slices
Built-in concurrency
Go missing parts (by intention…)
No inheritance
No constructors
No classes
No implements
No final
No exceptions
!!! Spoiler !!!
A restful API in Golang
Built with Makefile
Dockerized
Documented with Swagger
Tested with Cucumber
Good to know...
Next steps
Go by example (https://gobyexample.com)
Tutorial (https://tour.golang.org/welcome/1)
Effective go (https://golang.org/doc/effective_go.html)
Awesome Go: https://go.libhunt.com/
Recommended frameworks
Gorilla: http://www.gorillatoolkit.org/ OR https://github.com/emicklei/go-restful (with
Swagger)
BDD: https://github.com/DATA-DOG/godog
Configuration: https://github.com/spf13/viper
Logging: https://github.com/Sirupsen/logrus
CLI writing: https://github.com/spf13/cobra
Microservices: https://gokit.io/
Thank you!

Golang basics for Java developers - Part 1

  • 1.
    Golang basics… ...for Javadevelopers Robert Stern
  • 2.
    Agenda Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Java vs. Go
  • 3.
    All you needis… https://play.golang.org/
  • 4.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 5.
    History and features Createdin 2007 at Google, announced in 2009, v1.0 released in 2012) with strong dedication for server side programming. Compiled, statically typed, garbage collected language with multiple architecture/OS support (i386, amd64, arm/Windows, Linux, *BSD, etc..) (very) fast compilation AND execution time with low resource consumption Powerful cli (go get, go build, go test, go install…) Current stable version is 1.6.3 and still being actively developed
  • 6.
    What is missingor disturbing? No generics Not an OO language No constructors No operator/method overloading No circular package imports No mandatory semicolons GC pause is unpredictable
  • 7.
    What is non-java-isch? Multiplereturn values + the blank variable Golang is a pass-by-value language Lightweight concurrency with goroutines and channels No SE/EE separation. All server stuff is built-in. No exceptions, use error instead Compile time error about unused imports and variables No maven/ant like build system. Uses Makefile+vendoring+go get
  • 8.
    Famous projects, companies Projects: AppEngine with Go, AWS with Go SDK, Docker, Kubernetes, Grafana, Terraform, Gogs (Go Git Service), etcd, drone.io, Syncthing, CockroachDB, rkt, nsq, consul, boltDB, weave, swarm, vulcand, gryffin, fleet, minio… Companies: Google (of course…), Netflix, Dropbox, CloudFlare, SoundCloud, BBC, Uber, Couchbase, MongoDB...
  • 9.
  • 10.
    A bit biggerpicture about the trends
  • 11.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 12.
    Hello world ingolang: package main // imports import "fmt" /* This is the main function */ func main() { fmt.Println("Hello, World!") } Try it in the Go playground! Hello world
  • 13.
    Go project structure ❏Workspace ($GOPATH or %GOPATH%) ❏ src/pkg/bin roots ❏ Repository (github.com, etc…) ❏ Package ❏ Go source files
  • 14.
  • 15.
    Packages Like in Java,golang also uses packages to organize code, but in a bit different format. Keyword: package <name> The app starts in the main package. the path to the package’s directory is the import path The package name is the last element of the import path: github.com/zooplus/golang-app/stringutil → stringutil Accessing stringutil functions/elements: stringutil.<name>
  • 16.
    import ( "reflect" "strings" "github.com/emicklei/go-restful" ) import "reflect" import"strings" import "github.com/emicklei/go-restful" Importing packages
  • 17.
    Package types To useone or more functions in a package we need to import it into our code. We can import system, local and remote packages. System packages are the golang out of box packages like http, testing, etc.. Local package resides in your repository, no full path needed Remote packages has complete import path pointing to the server like: github.com/emicklei/go-restful
  • 18.
    Getting the dependencies Forremote packages use go get to fetch into your workspace. We have two syntaxes go get in the repository folder downloads all remote packages based on the imports go get <remote path> downloads the specified package for later use
  • 19.
    Variables, constants package main import"fmt" const greeting = "Hello" var name string func main() { name = "Zooplus" space := " " fmt.Println(greeting + space + name) }
  • 20.
    if _, err:= os.Stat(path); os.IsNotExist(err) { fmt.Printf("%s does not existn", path) } The blank identifier “The blank identifier can be assigned or declared with any value of any type, with the value discarded harmlessly” (https://golang.org/doc/effective_go.html#blank)
  • 21.
    Exported names “In Go,a name is exported if it begins with a capital letter. For example, Pizza is an exported name, as is Pi, which is exported from the math package.” package main import ( "fmt" "math" ) func main() { fmt.Println(math.pi) }
  • 22.
    Practice! Refactor the greetingapp to use fmt.Printf(format, args...)** and display the following message: Hello Zooplus, today is Friday. The name of the day as string can be printed with: import "time" ... time.Now().Format("Monday") **(Use %s for string)
  • 23.
    A solution package main import( "fmt" "time" ) func main() { name := "Zooplus" fmt.Printf("Hello %s, today is %s.", name, time.Now().Format("Monday")) }
  • 24.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 25.
    Basic types bool string int int8int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // alias for uint8 rune // alias for int32, represents a Unicode code point float32 float64 complex64 complex128 - “math/cmplx”: var number complex128 = cmplx.Sqrt(-5 + 12i)
  • 26.
    Pointers - bit.ly/2a58jnI packagemain import "fmt" func main() { i, j := 42, 2701 p := &i // point to i fmt.Println(*p) // read i through the pointer *p = 21 // set i through the pointer fmt.Println(i) // see the new value of i p = &j // point to j *p = *p / 37 // divide j through the pointer fmt.Println(j) // see the new value of j }
  • 27.
    package main var ( aint b int32 c int16 ) func main() { a = 1 b = a c = a } No autoboxing! You should convert your types by yourself. package main import "fmt" var ( a int b int32 c int16 ) func main() { a = 1 b = int32(a) c = int16(a) fmt.Printf("a: %d, b: %d, c: %d", a, b, c) } Type conversion prog.go:11: cannot use a (type int) as type int32 in assignment prog.go:12: cannot use a (type int) as type int16 in assignmenta: 1, b: 1, c: 1
  • 28.
    Struct type ApacheLogRecord struct{ ip string time string method, uri, protocol string status int responseBytes int referer string userAgent string } 1. result = &ApacheLogRecord{ ip: nvl(req.RemoteAddr), time: timeFormatted, method: nvl(req.Method), uri: nvl(req.URL.Path), protocol: nvl(req.Proto), status: resp.StatusCode(), responseBytes: resp.ContentLength(), referer: nvl(req.Referer()), userAgent: nvl(req.UserAgent()), } 2.) result = new(ApacheLogRecord)
  • 29.
    package main import "fmt" typeAnimal struct { legCount int } // define a behavior for Animal func (a Animal) numberOfLegs() int { return a.legCount } type Dog struct { Animal //anonymous field Animal } func main() { d := Dog{Animal{4}} //no method defined for Dog, but we have the same behavior as Animal. fmt.Println("A Dog has this many legs: ", d.numberOfLegs()) } Embedding, inheritance -bit.ly/2axY1yu
  • 30.
    Receiver methods -bit.ly/2a56VkS packagemain import "fmt" type Animal struct { legCount int } func (a Animal) numberOfLegs() int { return a.legCount } func (a Animal) setLegs(c int) { a.legCount = c } type Mammal struct { weight int } func (m Mammal) getWeight() int { return m.weight } func (m Mammal) setWeight(w int) { m.weight = w } type Dog struct { Animal Mammal } func main() { d := Dog{Animal{4}, Mammal{10}} fmt.Printf("A Dog has this many legs: %d oh... and weight: %d", d.numberOfLegs(), d.getWeight()) }
  • 31.
    Pointer receivers -bit.ly/2aKK7si packagemain import "fmt" type Animal struct { legCount int } func (a Animal) numberOfLegs() int { return a.legCount } func (a Animal) setLegs(c int) { a.legCount = c } func (a *Animal) setLegsPtr(c int) { a.legCount = c } type Dog struct { Animal //anonymous field Animal } func main() { d := Dog{Animal{4}} fmt.Println("A Dog has this many legs: ", d.numberOfLegs()) d.setLegs(5) fmt.Println("A Dog has this many legs: ", d.numberOfLegs()) d.setLegsPtr(6) fmt.Println("A Dog has this many legs: ", d.numberOfLegs()) }
  • 32.
    Arrays -bit.ly/2ahx5EA Arrays hasfix size and type with zero based indexing: var integers [20]int package main import "fmt" func main() { var a [2]string // std declaration a[0] = "Hello" a[1] = "Zooplus" fmt.Println(a[0], a[1]) fmt.Println(a) fibonacci := [6]int{1, 1, 2, 3, 5, 7} // on-the-fly declaration fmt.Println(fibonacci) }
  • 33.
    Slices - bit.ly/2ahVarP Sliceis a dynamic version of array (a sort of): var integers []int // decleration of a slice without size package main import "fmt" func main() { fibonacci := [6]int{1, 1, 2, 3, 5, 7} var p []int = fibonacci[1:4] fmt.Println(p) }
  • 34.
    Slices are notstoring data - bit.ly/2aai1Wx package main import "fmt" func main() { names := [4]string{ "John", "Paul", "George", "Ringo", } fmt.Println(names) a := names[0:2] b := names[1:3] fmt.Println(a, b) b[0] = "XXX" fmt.Println(a, b) fmt.Println(names) }
  • 35.
    Slices - bounds Thereare default low and high bounds for slices. Given the following array: var a [10]int The following slice declarations are equivalent: a[0:10] a[:10] a[0:] a[:]
  • 36.
    Creating slice: a :=make([]int, 5) // len(a)=5 Creating slice with capacity: b := make([]int, 0, 5) // len(b)=0, cap(b)=5 Appending slice: b = append(b, 10) Further reading: https://blog.golang.org/go-slices-usage-and-internals Slices - create, append
  • 37.
    Arrays, slices -for loop as foreach Iterate through an array/slice for index, value := range arr { fmt.Println("Index:", index, "Value:", value) } Get the index only: for index := range arr { fmt.Println("Index:", index) } Get the values: for _, value := range arr { fmt.Println("Value:", value) }
  • 38.
    Maps - declaration,initialization Maps are not initialized by default, we should use make: package main import "fmt" var m map[string]string func main() { m = make(map[string]string) m["Zooplus"] = "Gut" m["Bitiba"] = "Gut" m["Fressnapf"] = "Falsch" fmt.Println(m["Zooplus"]) }
  • 39.
    Maps - Mutatingmaps m[key] = item // upsert item = m[key] // retrieve delete (m, key) // guess…. _, ok = m[key] // ok == true if key exists, map can store/return nil Maps are not thread safe!!!
  • 40.
    Maps - forloop as foreach Iterate through a map: for key, value := range m { fmt.Println("Key:", key, "Value:", value) } Get the keys: for key := range m { fmt.Println("Key:", key) } Get the values: for _, value := range m { fmt.Println("Value:", value) }
  • 41.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 42.
    The one andonly: for loop // normal loop sum := 0 // init-condition-post for i := 0; i < 10; i++ { sum += i } fmt.Println(sum) // partial loop sum := 0 // init and post are optional for ; sum < 10; { sum += sum } // “while” loop sum := 1 // init and post are optional for sum < 1000 { sum += sum } fmt.Println(sum) // infinite loop for { }
  • 43.
    func GetProject(req *restful.Request,resp *restful.Response) { resp.Header().Set("Pragma", "no-cache") // pId := req.PathParameter("projectId") if project, ok := projects.GetProjectByIdOrName(pId); ok { ReturnJSON(resp, http.StatusOK, project) } ReturnMessage(resp, http.StatusNotFound, "Project not found!") } If-then-else existingPipeline, ok := nameSpace.Pipelines[newPipeline.Name] if ok { log.Debug("Entry exists!") } else { nameSpace.Pipelines[newPipeline.Name] = existingPipeline log.Debug("New entry stored") } ?
  • 44.
    Switch Switch in Golangis a bit different from Java: No automatic fallthrough, no need to put break at the end in every cases You can delegate expression evaluation into the case block fallthrough keyword for java-ish behavior Multiple conditions in one case (no empty cases like in java) Not limited to string and int Type switch can be used for interface{} to find out the real type (instanceof)
  • 45.
    Switch - nofallthrough by default switch c { case '&': esc = "&amp;" case ''': esc = "&apos;" case '<': esc = "&lt;" case '>': esc = "&gt;" case '"': esc = "&quot;" default: panic("unrecognized escape character") }
  • 46.
    Switch - stringsare welcome switch syscall.OS { case "windows": ... case "plan9": ... default: ... }
  • 47.
    Switch - (multiple)expression(s)in cases switch { case '0' <= c && c <= '9': return c - '0' case 'a' <= c && c <= 'f': return c - 'a' + 10 case 'A' <= c && c <= 'F': return c - 'A' + 10 } switch chars[code].category { case "de", "uk", "fr", "sp", "nl": return true }
  • 48.
    Switch - Typeswitch switch v.(type) { case int: return "int" case string: return "string" default: return "unknown" }
  • 49.
    Switch - youcan break it switch argv[0] { case "echo": fmt.Print(argv[1:]...) case "cat": if len(argv) <= 1 { fmt.Println("Usage: cat <filename>") break } PrintFile(argv[1]) default: fmt.Println("Unknown command; try 'echo' or 'cat'") }
  • 50.
    Switch - fallthrough switchlen(src) { default: v |= uint32(src[3]) fallthrough case 3: v |= uint32(src[2]) << 8 fallthrough case 2: v |= uint32(src[1]) << 16 fallthrough case 1: v |= uint32(src[0]) << 24 }
  • 51.
    Errors instead ofexceptions Golang has no exceptions and of course there are no checked exceptions :))))))) No try-catch-finally. Error is just an interface Functions are often returning a value and an error together. Checking this error for nil is the exception handling in Golang: // validate pipeline, err := validateYaml(buf.Bytes()) if err != nil { errorMessage := fmt.Sprintf("Error parsing pipeline config: %s", err) log.Error(errorMessage) http.Error(w, errorMessage, http.StatusBadRequest) } else {...} NO CHECKED EXCEPTIONS!!!
  • 52.
    Defer func CopyFile(dstName, srcNamestring) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } defer src.Close() dst, err := os.Create(dstName) if err != nil { return } defer dst.Close() defer fmt.Println(“All closed”) return io.Copy(dst, src) }
  • 53.
    Panic and Recover-bit.ly/2a5m0mJ func main() { f() fmt.Println("Returned normally from f.") } func f() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f", r) } }() fmt.Println("Calling g.") g(0) fmt.Println("Returned normally from g.") } func g(i int) { if i > 3 { fmt.Println("Panicking!") panic(fmt.Sprintf("%v", i)) } defer fmt.Println("Defer in g", i) fmt.Println("Printing in g", i) g(i + 1) }
  • 54.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 55.
    Functions -bit.ly/2a5mg4W package main import"fmt" func swap(x, y string) (string, string) { // also can use (x string, y string) return y, x } func main() { a, b := swap("hello", "zooplus") fmt.Println(a, b) }
  • 56.
    Functions -bit.ly/2aymMe6 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)) }
  • 57.
    Interfaces Golang has no“implements” keyword. If you implement all methods defined by the interface, then you are implemented the interface implicitly. package main import "fmt" type I interface { M() } type T struct { S string } // This method means type T implements the interface I, // but we don't need to explicitly declare that it does so. func (t T) M() { fmt.Println(t.S) } func main() { var i I = T{"hello"} i.M() }
  • 58.
    The empty interface- bit.ly/2awwq3Z Like Object in Java, Golang has the interface{} as type that compatible with every value (even with primitives). So it can hold any value. You need type assertion to find out what is it: package main import "fmt" func main() { var i interface{} = "hello" s := i.(string) fmt.Println(s) s, ok := i.(string) fmt.Println(s, ok) f, ok := i.(float64) fmt.Println(f, ok) f = i.(float64) // panic fmt.Println(f) }
  • 59.
    Reflection “In computer science,reflection is the ability of a computer program to examine and modify its own structure and behavior (specifically the values, meta-data, properties and functions) at runtime.” /Wikipedia/ Golang has a reflection package to inspect structs, interfaces or methods runtime like in Java and also you can change the values of the fields. What you’ll miss is some bytecode manipulation and proxy generation. Mockito like framework is not possible in Golang. See more: http://blog.ralch.com/tutorial/golang-reflection/
  • 60.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 61.
    Similarities with Java Goroutine= Thread Locks (R, RW) Atomic package thread safe variable handling Waitgroup = Join
  • 62.
    Differences from Java Goroutineis lightweight, but not reusable No Threadlocal or Executorservice in Golang Golang has no thread safe map implementation by default (https://github.com/streamrail/concurrent-map) Golang is a pass-by-value language Golang uses channels to communicate between threads Golang unsafe package is more limited To summarize: Java originally built-on the shared memory concept, but the Golang is focusing on the communication with channels
  • 63.
    Channels ch := make(chanint) // single item channel v:= 5 ch <- v // Send v to channel ch. v := <-ch // Receive from ch, and // assign value to v. ch := make(chan int,100) // buffered channel v:= 5 ch <- v // Send v to channel ch. v := <-ch // Receive from ch, and // assign value to v.
  • 64.
    Looping on achannel package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) for i := range c { fmt.Println(i) } }
  • 65.
    Overview Basic syntax andstructure Datatypes Flow control Functions, interfaces Concurrency Java vs. Go
  • 66.
    Go and Javacommon points C like (braces) Garbage collector Memory safety (nil/null references, runtime bounds checks) Statically typed Variables initialized by default(zero/nil/false) Methods, Interfaces
  • 67.
    Go and Javadifferences Native code without VM + statically linked binaries Control over memory layout Function values and lexical closures Built-in strings (UTF-8) Built-in generic maps and arrays/slices Built-in concurrency
  • 68.
    Go missing parts(by intention…) No inheritance No constructors No classes No implements No final No exceptions
  • 69.
  • 70.
    A restful APIin Golang Built with Makefile Dockerized Documented with Swagger Tested with Cucumber
  • 71.
  • 72.
    Next steps Go byexample (https://gobyexample.com) Tutorial (https://tour.golang.org/welcome/1) Effective go (https://golang.org/doc/effective_go.html) Awesome Go: https://go.libhunt.com/
  • 73.
    Recommended frameworks Gorilla: http://www.gorillatoolkit.org/OR https://github.com/emicklei/go-restful (with Swagger) BDD: https://github.com/DATA-DOG/godog Configuration: https://github.com/spf13/viper Logging: https://github.com/Sirupsen/logrus CLI writing: https://github.com/spf13/cobra Microservices: https://gokit.io/
  • 74.

Editor's Notes

  • #2 Just the basics...
  • #4 Before we start… https://play.golang.org/
  • #6 Good for APIs, webapps backend, servers, etc...
  • #7 ...for a java developer
  • #10 ANIMATED! Should we stop developing in java?
  • #11 ANIMATED! No… Java will stay here for long time
  • #14 A workspace is a directory hierarchy with three directories at its root: src contains Go source files, pkg contains package objects, and bin contains executable commands. The go tool builds source packages and installs the resulting binaries to the pkg and bin directories. The src subdirectory typically contains multiple version control repositories (such as for Git or Mercurial) that track the development of one or more source packages.
  • #15 The tree above shows a workspace containing two repositories (example and image). The example repository contains two commands (hello and outyet) and one library (stringutil). The image repository contains thebmp package and several others. A typical workspace contains many source repositories containing many packages and commands. Most Go programmers keep all their Go source code and dependencies in a single workspace.
  • #16 No static import in golang
  • #17 ANIMATED! Import has two formats, the last import is a remote package! What does it mean? Let’s talk about the package types
  • #19 So that’s all about the folders and dependencies, let’s start with the language elements
  • #20 ANIMATED! We have a package and we imported all stuff we need, so let’s declare some variables. Variable scopes: global with capitalized name, package local withotu capital, local to func/block, and short within if-s. Will be discussed there.
  • #21 ANIMATED! Use blank variable to ignore a return value, but use it carefully! An example from the os package.
  • #22 ANIMATED! Math.pi is not exported, invisible outside of the math package. Fix it to change pi to PI. then we are done with the basic syntax.
  • #25 Let’s talk about the golang basic types.
  • #26 ANIMATED! The building block of complex data structures. Int, uint and uintptr are 32/64 wide, depending on the system they run.
  • #27 Go has pointers. A pointer holds the memory address of a variable. This is from the tour of go site. bit.ly/2a58jnI
  • #28 ANIMATED!
  • #29 ANIMATED! Struct is a complex type which contains named fields
  • #30 ANIMATED! There’s no classical inheritance in Golang, because we are using EMBEDDING. It makes multiple inheritance and composition possible. Let’s see the example. Here we are inheriting the Dog’s method. But wait… What is this numberOfLegs stuff? bit.ly/2axY1yu This is a receiver method!
  • #31 We can attach methods to structs and they can invoked via the struct instances like the object methods in Java. No static methods for structs! This methods can be inherited with embedding and we can embed multiple items so we can inherit from multiple sources. THe a and m is representing the THIS in java. These are the VALUE receivers. They’re receiving the struct by value and the content can’t be changed. What to do if we want to mutate the content? The answer in the next slide… bit.ly/2a56VkS
  • #32 With pointer receiver we can change the value of the struct. bit.ly/2aKK7si
  • #33 You can’t resize the array, so if you need dynamic solution, you need something else.. Next slide… bit.ly/2ahx5EA
  • #34 An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays. Same structure existing in Python. So if you familiar with python, then the slice shouldn’t surprise you. Slices are like references to arrays. A slice does not store any data, it just describes a section of an underlying array. Changing the elements of a slice modifies the corresponding elements of its underlying array. Other slices that share the same underlying array will see those changes. bit.ly/2ahVarP
  • #35 Slice is a pointer to the underlying array. If you change the array, the slice is also changing. Quite familiar right? This is a nice example of the lightweight design pattern. bit.ly/2aai1Wx
  • #36 When slicing, you may omit the high or low bounds to use their defaults instead. The default is zero for the low bound and the length of the slice for the high bound.
  • #37  We can use make to create a slice from scratch. This is the way to create dynamic sized arrays, but we can’t decrease the size. The slice topic is quite big, I recommend to read the linked article about slice internals… Next slide: foreach
  • #38 A bit early to talk about for, but this is the right place for mentioning. Foreach for arrays and slices. First item is the index, second (optional) is the value. Next: maps
  • #39 Maps are quite huge topic, so only few feature are covered here. They’re the same key-value stuff like in java, but the implementation details are hidden (arraymap, linkedlistmap,etc… who knows?)
  • #40 Maps are quite huge topic, so only few feature are covered here. They’re the same key-value stuff like in java, but the implementation details are hidden (arraymap, linkedlistmap,etc… who knows?)
  • #41 Maps has key and value and golang can handle them in a for loop.
  • #43 ANIMATED! Golang has only one loop type: for. No while or do-while, nothing. Just the for. Golang for don’t need brackets. We can use for in multiple ways: Normal, partial, while, infinite or range (as foreach discussed later)
  • #44 ANIMATED! If like in java without braces, but we have an additional syntax: the short statement THe variable declared in short statement lives only within the if.
  • #49 With a type switch you can switch on the type of an interface value (only):
  • #51 The 'fallthrough' must be the last thing in the case! Not recommended if other structure can replace it. Next: errors
  • #52 ANIMATED!
  • #53 In Java 8 finally we’ve got the try-with-resources statement, to clean up things, but only works with Closeable interface. IMHO it’s a bit tight coupled, but works. Golang has bigger freedom, because we can specify any statement to run. You can specify the resource releasing mechanism right there where the resource occupied. Not just open/close, but lock/unlock is possible. Print a header then footer at the end. The defer evaluation order is Last In First Out so the println will run first.
  • #54 Panic is a built-in function that stops the ordinary flow of control and begins panicking.When panic called, the function stops, executes the defers normally, then return to its caller and the panicking continues until the app stops or... Recover is a built-in function that regains control of a panicking goroutine. Only usable as deferred function. In normal execution it returns a nil, otherwise the value given to the panic. The call recover() resumes the normal execution and stops panicking. Panic/Recover behaves like the exception handling in java. bit.ly/2a5m0mJ
  • #56 A function can take zero or more arguments and can return zero or more arguments. bit.ly/2a5mg4W
  • #57 Also you can give name the return value and they acting like a declared variable. In this case you don’t need to specify them in the return. bit.ly/2aymMe6
  • #59 bit.ly/2awwq3Z
  • #61 Concurrency is so big topic, we are just overviewing the golang specialities
  • #63 Goroutines are lightweight, but you can’t reuse them when they’re finished. You can create hundreds of goroutines quickly, no need of reuse or caching like in java. No executorservice or threadlocal Maps are not thread safe In golang the channels are used to share unit of work between threads, thread safe and you can define the capacity of the channel. Communicate over shared channels, and synchronized access is not necessary. Thread pooling is tricky in golang.
  • #64 Channel is a FIFO pipe with fix size. We can put and read items from a channel. The direction of the arrow shows the dataflow. This is a single item channel Channels are blocked and waiting to the data for indefinite time
  • #65 The common pattern for queue communication is the poison pill, to show to the receiver, no more data left and stop the operation. In golang we can close the channel to release the blocked reader. For-select skipped here, but used for timeouts
  • #69 Clarity and readability is critical in golang.
  • #71 The next session will be a workshop to develop an app