WHY AND
WHAT IS GO
Marko Jantke / Christian Speckner, Mayflower GmbH
A BRIEF
HISTORY
CONCEIVED 2007 AT
GOOGLE
Robert Griesemer
Rob Pike
Ken Thomson
...OF BELL LABS / UNIX FAME
...OF PLAN 9 FAME
The worst sci-fi movie ever
An experimental OS developed at Bell
Heritage visible in Go (toolchain!)
SOME DATES
First commit: 03/2008
Release 1.0 03/2012
Last release 1.7.1: 22 days ago
WHERE IS
GO?
POPULAR PROJECTS
WRITTEN IN GO
Docker
Kubernetes
etcd
Caddy
Consul
Mattermost
...
WHY IS GO?
THE AUTHORITATIVE
DOCUMENT
Go at Google: Language Design in the Service of Software
Engineering.
[https://talks.golang.org/2012/splash.article]
(And you'll be stumbling over Plan 9 more than once)
SOME DESIGN GOALS
Fast compilation cycles
Simple and concise syntax: easy to read, easy to parse
Familiarity for new developers
Scales well to large code bases
Promote robust and maintainable design
Keep large codebases robust in face of change
Offer maintainable paradigms for multithreading
INSIDE THE
GOPHER
STATICALLY TYPED
//Variabledeclaration
varsomeintint
varsomestringstring
varsomemapmap[string]int
//Typeinference
someint:=10
somestring:="Helloworld"
somemap:=make(map[string]int)
//Typedefinition
typeSometypestruct{
Field1int
Field2[]bool
}
//Functiondeclaration
funcFooinator(param1int,param2SomeStruct)string{
//Dosomething
}
IMPLICIT INTERFACES,
BUT NO CLASSES
packagemain
import(
"fmt"
"log"
"os"
)
typeDocinterface{}
typeDocumentStorageinterface{
Store(int,Doc)(error)
Get(int)(Doc,error)
}
typeMemoryStoragestruct{
docsmap[int]Doc
GARBAGE COLLECTED...
typeSomeStructstruct{
Field1string
Field2string
}
funcGenerator()SomeStruct{
returnSomeStruct{
Field1:"Hello",
Field2:"World",
}
}
... WITH POINTERS ...
typeSomeStructstruct{
Field1string
Field2string
}
funcGenerator()*SomeStruct{
return&SomeStruct{
Field1:"Hello",
Field2:"World",
}
}
... AND CLOSURES
funcFibonacciGenerator()(func()int){
f0:=0
f1:=1
returnfunc(){
oldF0:=f0
f0=f1
f1=oldF0+f1
returnf1
}
}
//...
f:=FibonacciGenerator()
fmt.Println(f(),f(),f(),f(),f(),f())//1235813
LIGHTWEIGHT THREADS
-> GOROUTINES
Scheduling (cooperative multithreading with multiple
threads)
Blocking
Communication (channels)
Races & mutexes
Embed code from golang/samples/interfaces.go
LIGHTWEIGHT THREADS ->
GOROUTINES
packagemain
import(
"fmt"
"time"
)
funcsaySomething(sstring,timesint){
fori:=0;i<times;i++{
time.Sleep(100*time.Millisecond)
fmt.Println(s)
}
}
funcmain(){
gosaySomething("hello",3)
gosaySomething("world",3)
saySomething("!",3)
}
//output:worldhello!worldhello!world!hello
LIGHTWEIGHT THREADS ->
GOROUTINES
packagemain
import(
"fmt"
)
funcsayHello(timesint,outputChannelchan<-string){
fori:=0;i<times;i++{
outputChannel<-"Hello"
}
}
funcsayWorld(timesint,inputChannel<-chanstring,outputChannelchan<-string
fori:=0;i<times;i++{
output:=<-inputChannel+"World!"
outputChannel<-output
}
}
funcprintString(timesint,inputChannel<-chanstring,outputChannelchan<-bool
fori:=0;i<times;i++{
output:=<-inputChannel
NO EXCEPTION
HANDLING, BUT...
Errors as values
Multiple return values
Defers
Panics and recover
NO EXCEPTION HANDLING, BUT...
packagemain
import(
"os"
"flag"
"log"
)
funcFileSize(pathstring)(int64,error){
fileInfo,err:=os.Stat(path)
iferr!=nil{
return0,err
}
returnfileInfo.Size(),nil
}
funcmain(){
varfilePathstring
flag.StringVar(&filePath,"filePath","","thefiletogetthesizeof"
flag.Parse()
HUGE STANDARD
LIBRARY
—
BATTERIES INCLUDED
HTTP SERVER
typehandlerint
func(h*handler)ServeHTTP(
responsehttp.ResponseWriter,
request*http.Request,
){
response.WriteHeader(http.StatusOK)
fmt.Fprintf(response,"thisisrequest#%vn",*h)
*h++
}
funcmain(){
i:=0
http.ListenAndServe(":8888",(*handler)(&i))
}
HTTP CLIENT
resp,err:=http.Get("http://www.mayflower.de")
varresponseBuffer[]byte
iferr==nil{
responseBuffer,err=ioutil.ReadAll(resp.Body)
}
iferr==nil{
fmt.Println(string(responseBuffer))
}else{
fmt.Printf("ERROR:%vn",err)
}
STREAM COMPRESSION
resp,err:=http.Get("http://www.mayflower.de")
iferr==nil{
writer:=gzip.NewWriter(os.Stdout)
_,err=io.Copy(writer,resp.Body)
iferr==nil{
writer.Close()
}
}
iferr!=nil{
fmt.Fprintf(os.Stderr,"ERROR:%vn",err)
}
AND MUCH, MUCH MORE...
Crypto, hashing
Marshalling / Unmarshalling (JSON, Base64, XML, ...)
Command line parsing
Complex numbers
JSON RPC
Reflection
Golang lexer and parser!
TOOLING
SWISS KNIVE: GO
goas interface to complete toolchain
go get
go build -x
go install
go test -race
go test -coverprofile=c.out
go tool cover -html=c.out
TOOLCHAIN
"NATIVE" TOOLCHAIN
This is the toolchain referred to in golang release
Rooted in Plan 9 toolchain (assembler, linker)
Used to be C, now Golang (converted from C)
Produces static binaries (not quite true anymore)
OS: Win, Linux, OSX, BSD and friends, Plan 9 (!), ...
Arch: x86, x86-64, ARM(v5678), ppc
Dead simple cross compilation
GOARCH=x86GOOS=windowsgoinstallsome/package
GCC FRONTEND
Lags behind native toolchain (currently 1.4 in GCC5)
Relies on GCC & friends for optimization, code
generation and linking
Generates dynamic binaries
Supports anything supported by GCC (MIPS anybody)
Cross compilation: PITA
INTERFACING C
Works with CGO: generates glue code
Dynamic dependencies: breaks cross compiling badly :(
BUT: Lots of native go out there :)
TESTING, PROFILING
AND CODE COVERAGE
[MARCO]
Testing files located by convention main.go ->
main_test.go
go test -cover -cpuprofile cpu.out -
memprofile mem.out
TESTING, PROFILING AND CODE
COVERAGE
packagemain
import"testing"
funcTestDivide(t*testing.T){
v,_:=Divide(10,5)
ifv!=2{
t.Error("Expected2,got:",v)
}
}
DEPENDENCY
MANAGEMENT
import"github.com/googollee/go-socket.io"
DEPENDENCIES CAN BE
AUTOMATICALLY IMPORTED
FROM GITHUB?
AWESOME!
AWESOME?
Pulls directly from git master
Stability?
Versioning?
API breaks?
REPRODUCIBLE BUILDS?
SOLUTION 1: GOPKG.IN
import"gopkg.in/yaml.v1"
$curlhttp://gopkg.in/yaml.v1?go-get=1
<html>
<head>
<metaname="go-import"content="gopkg.in/yaml.v1githttps://gopkg.in/yaml.v1">
<metaname="go-source"content="gopkg.in/yaml.v1_
https://github.com/go-yaml/yaml/tree/v1{/dir}
https://github.com/go-yaml/yaml/blob/v1{/dir}/{file}#L{line}">
</head>
<body>
gogetgopkg.in/yaml.v1
</body>
</html>
Redirects to fixed tags on github
Works well for small libraries
SOLUTION 2:
VENDORING
Record and pin dependencies in per-package manifest
Recursively download deps before build
Needs external tooling and per-package support :(
Popular specimen: glide
GOPHER
FODDER
PERFORMANT SERVERS
Event loop AND threads
Compiled and statically typed
Standard lib covers most networking stuff
Community frameworks for services: go-micro, go-kit
DEPENDENCY-LESS
UNIX-STYLE CLI TOOLS
Direct access to syscalls
Huge standard library
Supports script-like code style
Static binaries
EASY ACCESSIBLE
Fast entrance to the language
Great documentation
Parallel programming for everyone
NOT SO GOOD FOR
GOPHERS
GUI
Embedded
THANK YOU FOR
LISTENING
QUESTIONS?
Christian Speckner <christian.speckner@mayflower.de>
Marco Jantke <marco.jantke@mayflower.de>

Why and what is go