go by example

Upload: gteodorescu

Post on 04-Jun-2018

288 views

Category:

Documents


2 download

TRANSCRIPT

  • 8/13/2019 Go by Example

    1/91

    Go by Example

    Go is an open source programming language designed for building simple, fast, and reliablesoftware.

    Go by Example is a hands-on introduction to Go using annotated example programs. Checkout the first example or browse the full list below.

    Hello World

    Our first program will print the classichello world message. Here s the fullsource code.

    package main

    import "fmt"func main() { fmt.Println("hello world")}

    !o run the program, put the code in hello-world.go and use go run .

    $ go run hello-world.gohello world

    "ometimes we ll want to build our programsinto binaries. #e can do this using gobuild .

    $ go build hello-world.go$ lshello-world hello-world.go

    #e can then execute the built binar$directl$.

    $ ./hello-worldhello world

    %ow that we can run and build basic Go programs, let s learn more about thelanguage.

    &

    https://gobyexample.com/http://golang.org/https://gobyexample.com/hello-worldhttp://play.golang.org/p/H8bxSpw9Jqhttps://gobyexample.com/http://golang.org/https://gobyexample.com/hello-world
  • 8/13/2019 Go by Example

    2/91

    Values

    Go has 'arious 'alue t$pes including strings,integers, floats, booleans, etc. Here are a few basic examples.

    package mainimport "fmt"func main() {

    "trings, which can be added together with . fmt.Println("go" "lang")

    (ntegers and floats. fmt.Println("! ! "# ! !) fmt.Println(" .%/&.% "# .%/&.%)

    )ooleans, with boolean operators as $ou dexpect.

    fmt.Println(true '' false) fmt.Println(true false) fmt.Println( true)}

    $ go run *alues.gogolang! ! +.%/&.% +.&&&&&&&&&&&&&&&,falsetruefalse

    *

    http://play.golang.org/p/fgGVOyuZdu
  • 8/13/2019 Go by Example

    3/91

    Variables

    (n Go, variables are explicitl$ declared andused b$ the compiler to e.g. check t$pe-correctness of function calls.

    package mainimport "fmt"func main() {

    *ar declares & or more 'ariables. *ar a string "initial" fmt.Println(a)

    +ou can declare multiple 'ariables at once. *ar b# c int !# + fmt.Println(b# c)

    Go will infer the t$pe of initiali ed 'ariables. *ar d true fmt.Println(d)

    ariables declared without a correspondinginitiali ation are zero-valued . or example,the ero 'alue for an int is %.

    *ar e int fmt.Println(e)

    !he s$ntax is shorthand for declaring andinitiali ing a 'ariable, e.g. for *ar fstring "short" in this case.

    f "short" fmt.Println(f)}

    $ go run *ariables.goinitial! +true%short

    /

    http://play.golang.org/p/Zv45CSMaiD
  • 8/13/2019 Go by Example

    4/91

    Constants

    Go supports constants of character, string, boolean, and numeric 'alues.

    package mainimport "fmt"import "math"

    const declares a constant 'alue.const s string "constant"

    func main() { fmt.Println(s)

    0 const statement can appear an$where a*ar statement can.

    const n ,%%%%%%%%

    Constant expressions perform arithmeticwith arbitrar$ precision.

    const d &e+% / n fmt.Println(d)

    0 numeric constant has no t$pe until it sgi'en one, such as b$ an explicit cast.

    fmt.Println(int (d))

    0 number can be gi'en a t$pe b$ using it ina context that re1uires one, such as a

    'ariable assignment or function call. orexample, here math.0in expects a float .

    fmt.Println(math.0in(n))}

    $ go run constant.goconstante !!%%%%%%%%%%%-%.+1 % % &+& , %

    2

    http://play.golang.org/p/T5sj0eINnp
  • 8/13/2019 Go by Example

    5/91

    For

    for is Go s onl$ looping construct. Here arethree basic t$pes of for loops.

    package mainimport "fmt"func main() {

    !he most basic t$pe, with a single condition.

    i ! for i 2 & { fmt.Println(i) i i ! }

    0 classic initial3condition3after for loop.

    for 3 4 3 2 54 3 { fmt.Println(3) }

    for without a condition will loop repeatedl$until $ou break out of the loop or return from the enclosing function.

    for { fmt.Println("loop") break }}$ go run for.go!+&

    1

    5loop

    #e ll see some other for forms later whenwe look at range statements, channels, andother data structures.

    4

    http://play.golang.org/p/mGqqcBZ0jv
  • 8/13/2019 Go by Example

    6/91

    If/Else

    )ranching with if and else in Go isstraight-forward.

    package mainimport "fmt"func main() {

    Here s a basic example.

    if 6+ % { fmt.Println(" is e*en") } else { fmt.Println(" is odd") }

    +ou can ha'e an if statement without anelse.

    if 16 % { fmt.Println("1 is di*isible b7") }

    0 statement can precede conditionals5 an$'ariables declared in this statement area'ailable in all branches.

    if num 54 num 2 % { fmt.Println(num# "is negati*e") } else if num 2 !% { fmt.Println(num# "has ! digit") } else { fmt.Println(num# "has multipledigits") }}

    %ote that $ou don t need parentheses aroundconditions in Go, but that the brackets arere1uired.

    $ go run if-else.go is odd1 is di*isible b7 5 has ! digit

    !here is no ternar$ if in Go, so $ou ll needto use a full if statement e'en for basicconditions.

    6

    http://en.wikipedia.org/wiki/%3F:http://play.golang.org/p/p_ykufAYRjhttp://en.wikipedia.org/wiki/%3F:
  • 8/13/2019 Go by Example

    7/91

    Switch

    Switch statements express conditionalsacross man$ branches.

    package mainimport "fmt"import "time"func main() {

    Here s a basic switch .

    i + fmt.Print("write "# i# " as ") switch i { case ! fmt.Println("one") case + fmt.Println("two") case & fmt.Println("three") }

    +ou can use commas to separate multipleexpressions in the same case statement. #euse the optional default case in thisexample as well.

    switch time.8ow().9eekda7() { case time.0aturda7# time.0unda7 fmt.Println("it:s the weekend") default fmt.Println("it:s a weekda7") }

    switch without an expression is an alternatewa$ to express if3else logic. Here we alsoshow how the case expressions can be non-constants.

    t time.8ow() switch {

    case t.;our() 2 !+ fmt.Println("it:s before noon") default fmt.Println("it:s after noon") }}$ go run switch.gowrite + as twoit:s the weekendit:s before noon

    7

    http://play.golang.org/p/8b5CajPcHn
  • 8/13/2019 Go by Example

    8/91

    rrays

    (n Go, an array is a numbered se1uence ofelements of a specific length.

    package mainimport "fmt"func main() {

    Here we create an arra$ a that will holdexactl$ 4 int s. !he t$pe of elements andlength are both part of the arra$ s t$pe. )$default an arra$ is ero-'alued, which for

    int s means %s.

    *ar a

  • 8/13/2019 Go by Example

    9/91

    Slices

    Slices are a ke$ data t$pe in Go, gi'ing amore powerful interface to se1uences thanarra$s.

    package mainimport "fmt"func main() {

    8nlike arra$s, slices are t$ped onl$ b$ theelements the$ contain :not the number ofelements;. !o create an empt$ slice with

    non- ero length, use the builtin make . Herewe make a slice of string s of length & :initiall$ ero-'alued;.

    s make( fmt.Println("len "# len(s))

    (n addition to these basic operations, slicessupport se'eral more that make them richerthan arra$s. One is the builtin append , whichreturns a slice containing one or more new'alues. %ote that we need to accept a return'alue from append as we ma$ get a newslice 'alue.

    s append(s# "d") s append(s# "e"# "f") fmt.Println("apd "# s)

    "lices can also be cop7 d. Here we create anempt$ slice c of the same length as s and

    cop$ into c from s .

    c make(

  • 8/13/2019 Go by Example

    10/91

    #e can declare and initiali e a 'ariable forslice in a single line as well.

    t

  • 8/13/2019 Go by Example

    11/91

    !aps

    Maps are Go s built-in associati'e data t$pe :sometimes called hashes or dicts in otherlanguages;.

    package mainimport "fmt"func main() {

    !o create an empt$ map, use the builtinmake >make(map

  • 8/13/2019 Go by Example

    12/91

    "an#e

    range iterates o'er of elements in a 'ariet$of data structures. Aet s see how to userange with some of the data structureswe 'e alread$ learned.

    package mainimport "fmt"func main() {

    Here we use range to sum the numbers in a

    slice. 0rra$s work like this too.

    nums

  • 8/13/2019 Go by Example

    13/91

    Functions

    Functions are central in Go. #e ll learnabout functions with a few differentexamples.

    package mainimport "fmt"

    Here s a function that takes two int s andreturns their sum as an int .

    func plus(a int# b int) int {

    Go re1uires explicit returns, i.e. it won t

    automaticall$ return the 'alue of the lastexpression.

    return a b

    }

    func main() {

    Call a function

  • 8/13/2019 Go by Example

    14/91

    !ultiple "eturn Values

    Go has built-in support for multiple returnvalues . !his feature is used often inidiomatic Go, for example to return bothresult and error 'alues from a function.

    package mainimport "fmt"

    !he (int# int) in this function signatureshows that the function returns * int s.

    func *als() (int# int) { return }

    func main() {

    Here we use the * different return 'aluesfrom the call with multiple assignment .

    a# b *als() fmt.Println(a) fmt.Println(b)

    (f $ou onl$ want a subset of the returned'alues, use the blank identifier A.

    A# c *als() fmt.Println(c)}

    $ go run multiple-return-*alues.go&

    0ccepting a 'ariable number of arguments isanother nice feature of Go functions5 we lllook at this next.

    &2

    http://play.golang.org/p/LrDt1Wah0M
  • 8/13/2019 Go by Example

    15/91

    Variadic Functions

    ariadic functions can be called with an$number of trailing arguments. or example,fmt.Println is a common 'ariadicfunction.

    package mainimport "fmt"

    Here s a function that will take an arbitrar$number of ints as arguments.

    func sum(nums ...int) { fmt.Print(nums# " ") total % for A# num range nums { total num

    } fmt.Println(total)}func main() {

    ariadic functions can be called in the usualwa$ with indi'idual arguments.

    sum(!# +) sum(!# +# &)

    (f $ou alread$ ha'e multiple args in a slice,appl$ them to a 'ariadic function usingfunc(slice...) like this.

    nums 0nother ke$ aspect of functions in Go istheir abilit$ to form closures, which we lllook at next.

    &4

    http://en.wikipedia.org/wiki/Variadic_functionhttp://play.golang.org/p/wRPLOM1VIHhttp://en.wikipedia.org/wiki/Variadic_function
  • 8/13/2019 Go by Example

    16/91

    Closures

    Go supports anonymous functions , whichcan form closures . 0non$mous functions areuseful when $ou want to define a functioninline without ha'ing to name it.

    package mainimport "fmt"

    !his function int0eD returns anotherfunction, which we define anon$mousl$ inthe bod$ of int0eD . !he returned function

    closes over the 'ariable i to form a closure.

    func int0eD() func() int { i % return func() int { i ! return i

    }}func main() {

    #e call int0eD , assigning the result :afunction; to ne>tEnt . !his function 'aluecaptures its own i 'alue, which will beupdated each time we call ne>tEnt .

    ne>tEnt int0eD()

    "ee the effect of the closure b$ callingne>tEnt a few times.

    fmt.Println(ne>tEnt()) fmt.Println(ne>tEnt()) fmt.Println(ne>tEnt())

    !o confirm that the state is uni1ue to that particular function, create and test a newone.

    newEnts int0eD() fmt.Println(newEnts())}

    $ go run closures.go!+&!

    !he last feature of functions we ll look at for

    now is recursion.

    &6

    http://en.wikipedia.org/wiki/Anonymous_functionhttp://en.wikipedia.org/wiki/Closure_(computer_science)http://en.wikipedia.org/wiki/Closure_(computer_science)http://play.golang.org/p/gQtEWkhWyphttp://en.wikipedia.org/wiki/Anonymous_functionhttp://en.wikipedia.org/wiki/Closure_(computer_science)
  • 8/13/2019 Go by Example

    17/91

    "ecursion

    Go supports recursive functions . Here s aclassic factorial example.

    package mainimport "fmt"

    !his fact function calls itself until itreaches the base case of fact(%) .

    func fact(n int) int { if n % { return ! } return n F fact(n-!)}func main() { fmt.Println(fact( ))}$ go run recursion.go,% %

    &7

    http://en.wikipedia.org/wiki/Recursion_(computer_science)http://play.golang.org/p/RFn-rf42aphttp://en.wikipedia.org/wiki/Recursion_(computer_science)
  • 8/13/2019 Go by Example

    18/91

    $ointers

    Go supports pointers , allowing $ou to passreferences to 'alues and records within $our program.

    package mainimport "fmt"

    #e ll show how pointers work in contrast to'alues with * functions> Gero*al andGeroptr . Gero*al has an int parameter, soarguments will be passed to it b$ 'alue.

    Gero*al will get a cop$ of i*al distinctfrom the one in the calling function.

    func Gero*al(i*al int) { i*al %}

    Geroptr in contrast has an Fint parameter,meaning that it takes an int pointer. !heFiptr code in the function bod$ thendereferences the pointer from its memor$address to the current 'alue at that address.0ssigning a 'alue to a dereferenced pointerchanges the 'alue at the referenced address.

    func Geroptr(iptr Fint) { Fiptr %}

    func main() {

    i ! fmt.Println("initial "# i) Gero*al(i) fmt.Println("Gero*al "# i)

    !he 'i s$ntax gi'es the memor$ address ofi , i.e. a pointer to i .

    Geroptr('i) fmt.Println("Geroptr "# i)

    @ointers can be printed too. fmt.Println("pointer "# 'i)}

    Gero*al doesn t change the i in main , butGeroptr does because it has a reference tothe memor$ address for that 'ariable.

    $ go run pointers.goinitial !

    Gero*al !Geroptr %pointer %> +!&!!%%

    &9

    http://en.wikipedia.org/wiki/Pointer_(computer_programming)http://en.wikipedia.org/wiki/Pointer_(computer_programming)http://play.golang.org/p/KdE4TBbUL2http://en.wikipedia.org/wiki/Pointer_(computer_programming)
  • 8/13/2019 Go by Example

    19/91

    Structs

    Go s structs are t$ped collections of fields.!he$ re useful for grouping data together toform records.

    package mainimport "fmt"

    !his person struct t$pe has name and age fields.

    t7pe person struct { name string age int}func main() {

    !his s$ntax creates a new struct. fmt.Println(person{"Hob"# +%})

    +ou can name the fields when initiali ing astruct.

    fmt.Println(person{name "Ilice"#age &%})

    Omitted fields will be ero-'alued. fmt.Println(person{name "Jred"})

    0n ' prefix $ields a pointer to the struct. fmt.Println('person{name "Inn"#age %})

    0ccess struct fields with a dot. s person{name "0ean"# age ,%} fmt.Println(s.name)

    +ou can also use dots with struct pointers -the pointers are automaticall$ dereferenced.

    sp 's fmt.Println(sp.age)

    "tructs are mutable.

    sp.age ,! fmt.Println(sp.age)}$ go run structs.go{Hob +%}{Ilice &%}{Jred %}'{Inn %}0ean

    ,%,!

    &=

    http://play.golang.org/p/OMCP5KFC10
  • 8/13/2019 Go by Example

    20/91

    !ethods

    Go supports methods defined on struct t$pes.package mainimport "fmt"t7pe rect struct { width# height int}

    !his area method has a receiver type ofFrect .

    func (r Frect) area() int { return r.width F r.height}

    Bethods can be defined for either pointer or'alue recei'er t$pes. Here s an example of a'alue recei'er.

    func (r rect) perim() int {

    return +Fr.width +Fr.height}

    func main() { r rect{width !%# height ,}

    Here we call the * methods defined for ourstruct.

    fmt.Println("area "# r.area()) fmt.Println("perim "# r.perim())

    Go automaticall$ handles con'ersion between 'alues and pointers for method

    calls. +ou ma$ want to use a pointerrecei'er t$pe to a'oid cop$ing on methodcalls or to allow the method to mutate therecei'ing struct.

    rp 'r fmt.Println("area "# rp.area())

    fmt.Println("perim "# rp.perim())}

    $ go run methods.goarea ,%perim &%area ,%perim &%

    %ext we ll look at Go s mechanism forgrouping and naming related sets ofmethods> interfaces.

    *?

    http://play.golang.org/p/254m_9Yjwa
  • 8/13/2019 Go by Example

    21/91

    Interfaces

    !nterfaces are named collections of methodsignatures.

    package mainimport "fmt"import "math"

    Here s a basic interface for geometricshapes.

    t7pe geometr7 interface { area() float perim() float}

    or our example we ll implement thisinterface on sDuare and circle t$pes.

    t7pe sDuare struct { width# height float}t7pe circle struct { radius float}

    !o implement an interface in Go, we

  • 8/13/2019 Go by Example

    22/91

    !o learn more about Go s interfaces, checkout this great blog post .

    **

    http://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-gohttp://jordanorelli.tumblr.com/post/32665860244/how-to-use-interfaces-in-go
  • 8/13/2019 Go by Example

    23/91

  • 8/13/2019 Go by Example

    24/91

    !he two loops below test out each of

    our error-returning functions. %otethat the use of an inline error checkon the if line is a common idiom inGo code.

    for A# i range

  • 8/13/2019 Go by Example

    25/91

    Goroutines

    0 goroutine is a lightweight thread ofexecution.

    package mainimport "fmt"func f(from string) { for i %4 i 2 &4 i { fmt.Println(from# " "# i) }}func main() {

    "uppose we ha'e a function call f(s) .Here s how we d call that in the usual wa$,running it s$nchronousl$.

    f("direct")

    !o in'oke this function in a goroutine, usego f(s) . !his new goroutine will executeconcurrentl$ with the calling one.

    go f("goroutine")

    +ou can also start a goroutine for ananon$mous function call.

    go func(msg string) { fmt.Println(msg) }("going")

    Our two goroutines are runningas$nchronousl$ in separate goroutines now,so execution falls through to here. !his0canln code re1uires we press a ke$ beforethe program exits.

    *ar input string fmt.0canln('input) fmt.Println("done")}

    #hen we run this program, we see theoutput of the blocking call first, then theinterlea'ed output of the two gouroutines.

    !his interlea'ing reflects the goroutines being run concurrentl$ b$ the Go runtime.

    $ go run goroutines.godirect %direct !direct +goroutine %going

    goroutine !goroutine +2enterBdone

    %ext we ll look at a complement togoroutines in concurrent Go programs>channels.

    *4

    http://play.golang.org/p/aIO_Wi3hJj
  • 8/13/2019 Go by Example

    26/91

    Channels

    "hannels are the pipes that connectconcurrent goroutines. +ou can send 'aluesinto channels from one goroutine andrecei'e those 'alues into another goroutine.Channels are a powerful primiti'e thatunderl$ much of Go s functionalit$.

    package mainimport "fmt"func main() {

    Create a new channel with make(chan *al-t7pe) . Channels are t$ped b$ the 'aluesthe$ con'e$.

    messages make(chan string)

    Send a 'alue into a channel using thechannel 2- s$ntax. Here we send "ping" to the messages channel we made abo'e,from a new goroutine.

    go func() { messages 2- "ping" }()

    !he 2-channel s$ntax receives a 'alue fromthe channel. Here we ll recei'e the "ping" message we sent abo'e and print it out.

    msg 2-messages fmt.Println(msg)}

    #hen we run the program the "ping" message is succesfull$ passed from onegoroutine to another 'ia our channel.

    $ go run channels.goping

    )$ default sends and recei'es block until both the sender and recei'er are read$. !his propert$ allowed us to wait at the end of our program for the "ping" message without

    ha'ing to use an$ other s$nchroni ation.

    *6

    http://play.golang.org/p/aVTMoY5FNt
  • 8/13/2019 Go by Example

    27/91

    Channel %ufferin#

    )$ default channels are unbuffered , meaningthat the$ will onl$ accept sends : chan 2- ; ifthere is a corresponding recei'e : 2- chan ;read$ to recei'e the sent 'alue. #ufferedchannels accept a limited number of 'alueswithout a corresponding recei'er for those'alues.

    package mainimport "fmt"func main() {

    Here we make a channel of strings bufferingup to * 'alues.

    messages make(chan string# +)

    )ecause this channel is buffered, we cansend these 'alues into the channel without acorresponding concurrent recei'e.

    messages 2- "buffered" messages 2- "channel"

    Aater we can recei'e these two 'alues asusual.

    fmt.Println(2-messages) fmt.Println(2-messages)}

    $ go run channel-buffering.go

    bufferedchannel

    *7

    http://play.golang.org/p/34PVHwO6Bn
  • 8/13/2019 Go by Example

    28/91

    Channel Synchroni&ation

    #e can use channels to s$nchroni eexecution across goroutines. Here s anexample of using a blocking recei'e to waitfor a goroutine to finish.

    package mainimport "fmt"import "time"

    !his is the function we ll run in a goroutine.!he done channel will be used to notif$another goroutine that this function s work isdone.

    func worker(done chan bool) { fmt.Print("working...") time.0leep(time.0econd)

    fmt.Println("done")

    "end a 'alue to notif$ that we re done. done 2- true}

    func main() {

    "tart a worker goroutine, gi'ing it thechannel to notif$ on.

    done make(chan bool# !) go worker(done)

    )lock until we recei'e a notification fromthe worker on the channel.

    2-done}

    $ go run channel-s7nchroniGation.goworking...done

    (f $ou remo'ed the 2- done line from this program, the program would exit before theworker e'en started.

    *9

    http://play.golang.org/p/0DfW-1RMqi
  • 8/13/2019 Go by Example

    29/91

    Channel 'irections

    #hen using channels as function parameters, $ou can specif$ if a channel ismeant to onl$ send or recei'e 'alues. !hisspecificit$ increases the t$pe-safet$ of the

    program.

    package mainimport "fmt"

    !his ping function onl$ accepts a channelfor sending 'alues. (t would be a compile-

    time error to tr$ to recei'e on this channel.

    func ping(pings chan2- string# msgstring) { pings 2- msg}

    !he pong function accepts one channel forrecei'es : pings ; and a second for sends:pongs ;.

    func pong(pings 2-chan string# pongschan2- string) { msg 2-pings pongs 2- msg}func main() { pings make(chan string# !) pongs make(chan string# !) ping(pings# "passed message") pong(pings# pongs) fmt.Println(2-pongs)}

    $ go run channel-directions.gopassed message

    *=

    http://play.golang.org/p/P9Fujfpa1f
  • 8/13/2019 Go by Example

    30/91

    Select

    Go s select lets $ou wait on multiplechannel operations. Combininggoroutines and channels with selectis powerful feature of Go.

    package mainimport "time"import "fmt"func main() {

    or our example we ll select acrosstwo channels.

    c! make(chan string) c+ make(chan string)

    Each channel will recei'e a 'alueafter some amount of time, tosimulate e.g. blocking D@Coperations executing in concurrentgoroutines.

    go func() { time.0leep(time.0econd F !) c! 2- "one" }() go func() { time.0leep(time.0econd F +) c+ 2- "two" }()

    #e ll use select to await both ofthese 'alues simultaneousl$, printingeach one as it arri'es.

    for i %4 i 2 +4 i { select { case msg! 2-c! fmt.Println("recei*ed"# msg!) case msg+ 2-c+ fmt.Println("recei*ed"# msg+) } }}

    #e recei'e the 'alues "one" andthen "two" as expected.

    $ time go run select.gorecei*ed onerecei*ed two

    %ote that the total execution time isonl$ F* seconds since both the & and* second 0leeps executeconcurrentl$.

    real %m+.+ ,s

    /?

    http://play.golang.org/p/NGSkDrli6L
  • 8/13/2019 Go by Example

    31/91

    (imeouts

    $imeouts are important for programsthat connect to external resources orthat otherwise need to boundexecution time. (mplementingtimeouts in Go is eas$ and elegantthanks to channels and select .

    package mainimport "time"import "fmt"func main() {

    or our example, suppose we reexecuting an external call that returnsits result on a channel c! after *s.

    c! make(chan string# !) go func() { time.0leep(time.0econd F +) c! 2- "result !" }()

    Here s the select implementing atimeout. res 2-c! awaits theresult and 2-Lime.Ifter awaits a'alue to be sent after the timeout of&s. "ince select proceeds with thefirst recei'e that s read$, we ll take

    the timeout case if the operationtakes more than the allowed &s.

    select { case res 2-c! fmt.Println(res) case 2-time.Ifter(time.0econd F !) fmt.Println("timeout !") }

    (f we allow a longer timeout of /s,then the recei'e from c+ will succeedand we ll print the result.

    c+ make(chan string# !) go func() { time.0leep(time.0econd F +) c+ 2- "result +" }() select { case res 2-c+ fmt.Println(res) case 2-time.Ifter(time.0econd F &) fmt.Println("timeout +") }}

    Dunning this program shows the firstoperation timing out and the secondsucceeding.

    $ go run timeouts.gotimeout !result +

    8sing this select timeout patternre1uires communicating results o'erchannels. !his is a good idea ingeneral because other important Go

    features are based on channels andselect . #e ll look at two examples

    /&

    http://play.golang.org/p/CoBnJiRyx3
  • 8/13/2019 Go by Example

    32/91

    of this next> timers and tickers.

    )on*%loc+in# Channel ,perations

    )asic sends and recei'es on channelsare blocking. Howe'er, we can useselect with a default clause toimplement non-blocking sends,recei'es, and e'en non-blockingmulti-wa$ select s.

    package mainimport "fmt"

    func main() { messages make(chan string) signals make(chan bool)

    Here s a non-blocking recei'e. (f a'alue is a'ailable on messages thenselect will take the 2-messages case with that 'alue. (f not it willimmediatel$ take the default case.

    select { case msg 2-messages fmt.Println("recei*ed message"# msg) default fmt.Println("no message recei*ed") }

    0 non-blocking send workssimilarl$.

    msg "hi" select { case messages 2- msg fmt.Println("sent message"# msg) default fmt.Println("no message sent") }

    #e can use multiple case s abo'e thedefault clause to implement amulti-wa$ non-blocking select. Herewe attempt non-blocking recei'es on

    both messages and signals .

    select { case msg 2-messages fmt.Println("recei*ed message"# msg) case sig 2-signals fmt.Println("recei*ed signal"# sig) default fmt.Println("no acti*it7") }}$ go run non-blocking-channel-operations.gono message recei*edno message sentno acti*it7

    /*

    http://play.golang.org/p/M972dltae2
  • 8/13/2019 Go by Example

    33/91

    Closin# Channels

    "losing a channel indicates thatno more 'alues will be sent onit. !his can be useful tocommunicate completion to thechannel s recei'ers.

    package mainimport "fmt"

    (n this example we ll use a 3obschannel to communicate work

    to be done from the main() goroutine to a worker goroutine.#hen we ha'e no more

  • 8/13/2019 Go by Example

    34/91

    !he idea of closed channelsleads naturall$ to our nextexample> range o'er channels.

    "an#e o-er Channels

    (n a pre'ious example we saw how for andrange pro'ide iteration o'er basic datastructures. #e can also use this s$ntax toiterate o'er 'alues recei'ed from a channel.

    package mainimport "fmt"

    func main() {

    #e ll iterate o'er * 'alues in the Dueue channel.

    Dueue make(chan string# +) Dueue 2- "one" Dueue 2- "two" close(Dueue)

    !his range iterates o'er each element as it srecei'ed from Dueue . )ecause we close dthe channel abo'e, the iteration terminatesafter recei'ing the * elements. (f we didn tclose it we d block on a /rd recei'e in theloop.

    for elem range Dueue { fmt.Println(elem) }}

    $ go run range-o*er-channels.goonetwo

    !his example also showed that it s possibleto close a non-empt$ channel but still ha'ethe remaining 'alues be recei'ed.

    /2

    https://gobyexample.com/rangehttp://play.golang.org/p/WN7NNh9tvhhttps://gobyexample.com/range
  • 8/13/2019 Go by Example

    35/91

    (imers

    #e often want to execute Go code atsome point in the future, orrepeatedl$ at some inter'al. Go s

    built-in timer and ticker featuresmake both of these tasks eas$. #e lllook first at timers and then attickers .

    package mainimport "time"import "fmt"func main() {

    !imers represent a single e'ent in thefuture. +ou tell the timer how long$ou want to wait, and it pro'ides achannel that will be notified at thattime. !his timer will wait * seconds.

    timer! time.8ewLimer(time.0econd F +)

    !he 2-timer!.M blocks on thetimer s channel M until it sends a'alue indicating that the timer

    expired.

    2-timer!.M fmt.Println("Limer ! e>pired")

    (f $ou

  • 8/13/2019 Go by Example

    36/91

    (ic+ers

    !imers are for when $ou want to dosomething once in the future - tickers arefor when $ou want to do somethingrepeatedl$ at regular inter'als. Here s anexample of a ticker that ticks

    periodicall$ until we stop it.

    package mainimport "time"import "fmt"func main() {

    !ickers use a similar mechanism totimers> a channel that is sent 'alues.Here we ll use the range builtin on thechannel to iterate o'er the 'alues as the$arri'e e'er$ 4??ms.

    ticker time.8ewLicker(time.Nillisecond F ,%%) go func() { for t range ticker.M { fmt.Println("Lick at"# t) } }()

    !ickers can be stopped like timers. Oncea ticker is stopped it won t recei'e an$more 'alues on its channel. #e ll stopours after &4??ms.

    time.0leep(time.Nillisecond F !,%%) ticker.0top() fmt.Println("Licker stopped")}

    #hen we run this program the tickershould tick / times before we stop it.

    $ go run tickers.goLick at +%!+-%5-+& !! +5 , . 1 +, -% %%P?LLick at +%!+-%5-+& !! +5 , .511% & -% %%P?LLick at +%!+-%5-+& !! +5 , . 11% -% %%P?LLicker stopped

    /6

    https://gobyexample.com/timershttp://play.golang.org/p/U0PO7ZZU3lhttps://gobyexample.com/timers
  • 8/13/2019 Go by Example

    37/91

    Wor+er $ools

    (n this example we ll look at how toimplement a worker pool using goroutinesand channels.

    package mainimport "fmt"import "time"

    Here s the worker, of which we ll runse'eral concurrent instances. !hese workerswill recei'e work on the 3obs channel and

    send the corresponding results on results .#e ll sleep a second per

  • 8/13/2019 Go by Example

    38/91

    "ate .imitin#

    %ate limiting is an importantmechanism for controlling resourceutili ation and maintaining 1ualit$ ofser'ice. Go elegantl$ supports ratelimiting with goroutines, channels,and tickers .

    package mainimport "time"import "fmt"func main() {

    irst we ll look at basic rate limiting."uppose we want to limit ourhandling of incoming re1uests. #e llser'e these re1uests off a channel ofthe same name.

    reDuests make(chan int# ,) for i !4 i 2 ,4 i { reDuests 2- i } close(reDuests)

    !his limiter channel will recei'e a'alue e'er$ *?? milliseconds. !his isthe regulator in our rate limitingscheme.

    limiter time.Lick(time.Nillisecond F+%%)

    )$ blocking on a recei'e from thelimiter channel before ser'ing eachre1uest, we limit oursel'es to &re1uest e'er$ *?? milliseconds.

    for reD range reDuests { 2-limiter fmt.Println("reDuest"# reD#time.8ow()) }

    #e ma$ want to allow short bursts ofre1uests in our rate limiting schemewhile preser'ing the o'erall ratelimit. #e can accomplish this b$

    buffering our limiter channel. !hisburst7@imiter channel will allow

    bursts of up to / e'ents.

    burst7@imiter make(chan time.Lime# &)

    ill up the channel to representallowed bursting.

    for i %4 i 2 &4 i { burst7@imiter 2- time.8ow() }

    E'er$ *?? milliseconds we ll tr$ toadd a new 'alue to burst7@imiter ,up to its limit of /.

    go func() { for t rangetime.Lick(time.Nillisecond F +%%) { burst7@imiter 2- t } }()

    %ow simulate 4 more incomingburst7OeDuests make(chan int# ,) for i !4 i 2 ,4 i {

    burst7OeDuests 2- i

    /9

    http://en.wikipedia.org/wiki/Rate_limitinghttps://gobyexample.com/tickershttp://play.golang.org/p/e7yzIk97-phttp://en.wikipedia.org/wiki/Rate_limitinghttps://gobyexample.com/tickers
  • 8/13/2019 Go by Example

    39/91

    re1uests. !he first / of these will benefit from the burst capabilit$ ofburst7@imiter .

    } close(burst7OeDuests) for reD range burst7OeDuests { 2-burst7@imiter fmt.Println("reDuest"# reD#time.8ow())

    }}

    Dunning our program we see the first batch of re1uests handled once e'er$F*?? milliseconds as desired.

    $ go run rate-limiting.goreDuest ! +%!+-!%-!5 %% &1 !1. 1 &1 %%%%LMreDuest + +%!+-!%-!5 %% &1 !1.11 ! %%%%LMreDuest & +%!+-!%-!5 %% &1 !5.%1 +&1 %%%%LMreDuest +%!+-!%-!5 %% &1 !5.+1 &&1 %%%%LMreDuest , +%!+-!%-!5 %% &1 !5. 1 &&! %%%%LM

    or the second batch of re1uests weser'e the first / immediatel$ becauseof the burstable rate limiting, thenser'e the remaining * with F*??msdela$s each.

    reDuest ! +%!+-!%-!5 %% &1 +%. 1 , 1 %%%%LMreDuest + +%!+-!%-!5 %% &1 +%. 1 , %%%%LMreDuest & +%!+-!%-!5 %% &1 +%. 1 %%%%LMreDuest +%!+-!%-!5 %% &1 +%. 1 1& %%%%LMreDuest , +%!+-!%-!5 %% &1 +%.11 , + %%%%LM

    /=

  • 8/13/2019 Go by Example

    40/91

    tomic Counters

    !he primar$ mechanism formanaging state in Go iscommunication o'er channels. #esaw this for example with worker

    pools . !here are a few other optionsfor managing state though. Herewe ll look at using the s7nc/atomic

    package for atomic counters accessed b$ multiple goroutines.

    package mainimport "fmt"import "time"import "s7nc/atomic"import "runtime"func main() {

    #e ll use an unsigned integer torepresent our :alwa$s-positi'e;counter.

    *ar ops uint %

    !o simulate concurrent updates,we ll start 4? goroutines that eachincrement the counter about once amillisecond.

    for i %4 i 2 ,%4 i { go func() { for {

    !o atomicall$ increment the counterwe use Idd int , gi'ing it thememor$ address of our ops counterwith the ' s$ntax.

    atomic.Idd int ('ops# !)

    0llow other goroutines to proceed.

    runtime.Qosched() } }() }

    #ait a second to allow some ops toaccumulate.

    time.0leep(time.0econd)

    (n order to safel$ use the counterwhile it s still being updated b$ othergoroutines, we extract a cop$ of thecurrent 'alue into opsJinal 'ia@oad int . 0s abo'e we need togi'e this function the memor$

    address 'ops from which to fetch the'alue.

    opsJinal atomic.@oad int ('ops) fmt.Println("ops "# opsJinal)}

    2?

    https://gobyexample.com/worker-poolshttps://gobyexample.com/worker-poolshttp://play.golang.org/p/2h8nvrnaHPhttps://gobyexample.com/worker-poolshttps://gobyexample.com/worker-pools
  • 8/13/2019 Go by Example

    41/91

    Dunning the program shows that weexecuted about 2?,??? operations.

    $ go run atomic-counters.goops %+%%

    %ext we ll look at mutexes, anothertool for managing state.

    2&

  • 8/13/2019 Go by Example

    42/91

  • 8/13/2019 Go by Example

    43/91

    for blocking calls like time.0leep , but in this case we need to do itmanuall$.

    #e ll also start &? goroutines tosimulate writes, using the same

    pattern we did for reads.

    for w %4 w 2 !%4 w {

    go func() { for { ke7 rand.Entn(,) *al rand.Entn(!%%) mute>.@ock() state. nlock() atomic.IddEnt ('ops# !) runtime.Qosched() } }() }

    Aet the &? goroutines work on thestate and mute> for a second.

    time.0leep(time.0econd)

    !ake and report a final operationscount.

    opsJinal atomic.@oadEnt ('ops) fmt.Println("ops "# opsJinal)

    #ith a final lock of state , showhow it ended up.

    mute>.@ock() fmt.Println("state "# state) mute>. nlock()}

    Dunning the program shows that weexecuted about /,4??,??? operationsagainst our mute> -s$nchroni edstate .

    $ go run mute>es.goops &,51&%+state map

    %ext we ll look at implementing thissame state management task usingonl$ goroutines and channels.

    2/

  • 8/13/2019 Go by Example

    44/91

    Stateful Goroutines

    (n the pre'ious example we usedexplicit locking with mutexes tos$nchroni e access to shared stateacross multiple goroutines. 0notheroption is to use the built-ins$nchroni ation features ofgoroutines and channels to achie'ethe same result. !his channel-basedapproach aligns with Go s ideas ofsharing memor$ b$ communicatingand ha'ing each piece of data owned

    b$ exactl$ & goroutine.package mainimport ( "fmt" "math/rand" "s7nc/atomic" "time")

    (n this example our state will beowned b$ a single goroutine. !his

    will guarantee that the data is ne'ercorrupted with concurrent access. (norder to read or write that state, othergoroutines will send messages to theowning goroutine and recei'ecorresponding replies. !hese readRp and writeRp struct s encapsulatethose re1uests and a wa$ for theowning goroutine to respond.

    t7pe readRp struct {

    ke7 int resp chan int}t7pe writeRp struct { ke7 int *al int resp chan bool}

    func main() {

    0s before we ll count how man$operations we perform.

    *ar ops int %

    !he reads and writes channels will be used b$ other goroutines to issueread and write re1uests, respecti'el$.

    reads make(chan FreadRp) writes make(chan FwriteRp)

    Here is the goroutine that owns thestate , which is a map as in the

    pre'ious example but now pri'ate to

    the stateful goroutine. !his goroutinerepeatedl$ selects on the reads and

    go func() { *ar state make(map

  • 8/13/2019 Go by Example

    45/91

    writes channels, responding tore1uests as the$ arri'e. 0 response isexecuted b$ first performing there1uested operation and then sendinga 'alue on the response channel respto indicate success :and the desired'alue in the case of reads ;.

    write.resp 2- true } }

    }()

    !his starts &?? goroutines to issuereads to the state-owning goroutine'ia the reads channel. Each readre1uires constructing a readRp ,sending it o'er the reads channel,and the recei'ing the result o'er the

    pro'ided resp channel.

    for r %4 r 2 !%%4 r { go func() { for { read 'readRp{ ke7 rand.Entn(,)# resp make(chan int)} reads 2- read 2-read.resp atomic.IddEnt ('ops# !)

    } }() }

    #e start &? writes as well, using asimilar approach.

    for w %4 w 2 !%4 w { go func() { for { write 'writeRp{ ke7 rand.Entn(,)# *al rand.Entn(!%%)# resp make(chan bool)} writes 2- write 2-write.resp atomic.IddEnt ('ops# !)

    } }() }

    Aet the goroutines work for a second. time.0leep(time.0econd)

    inall$, capture and report the ops count.

    opsJinal atomic.@oadEnt ('ops) fmt.Println("ops "# opsJinal)}

    Dunning our program shows that thegoroutine-based state management

    example achie'es about 9??,???operations per second.

    $ go run stateful-goroutines.goops 1% &

    or this particular case the goroutine- based approach was a bit morein'ol'ed than the mutex-based one.(t might be useful in certain casesthough, for example where $ou ha'eother channels in'ol'ed or whenmanaging multiple such mutexeswould be error-prone. +ou shoulduse whiche'er approach feels mostnatural, especiall$ with respect to

    24

  • 8/13/2019 Go by Example

    46/91

  • 8/13/2019 Go by Example

    47/91

    Sortin#

    Go s sort package implementssorting for builtins and user-definedt$pes. #e ll look at sorting for

    builtins first.

    package mainimport "fmt"import "sort"func main() {

    "ort methods are specific to the builtin t$pe5 here s an example forstrings. %ote that sorting is in-place,so it changes the gi'en slice anddoesn t return a new one.

    strs

  • 8/13/2019 Go by Example

    48/91

    Sortin# by Functions

    "ometimes we ll want to sort acollection b$ something other thanits natural order. or example,suppose we wanted to sort strings b$their length instead of alphabeticall$.Here s an example of custom sortssorts in Go.

    package mainimport "sort"import "fmt"

    (n order to sort b$ a custom functionin Go, we need a corresponding t$pe.Here we 'e created a H7@ength t$pethat is

  • 8/13/2019 Go by Example

    49/91

    2=

  • 8/13/2019 Go by Example

    50/91

    $anic

    0 panic t$picall$ means something wentunexpectedl$ wrong. Bostl$ we use it to failfast on errors that shouldn t occur duringnormal operation, or that we aren t preparedto handle gracefull$.

    package mainimport "os"func main() {

    #e ll use panic throughout this site to check

    for unexpected errors. !his is the onl$ program on the site designed to panic.

    panic("a problem")

    0 common use of panic is to abort if afunction returns an error 'alue that we don tknow how to :or want to; handle. Here s anexample of panic king if we get anunexpected error when creating a new file.

    A# err os.Mreate("/tmp/file") if err nil { panic(err) }}

    Dunning this program will cause it to panic, print an error message and goroutine traces,and exit with a non- ero status.

    $ go run panic.gopanic a problem

    goroutine ! ...e>it status +

    %ote that unlike some languages which useexceptions for handling of man$ errors, inGo it is idiomatic to use error-indicatingreturn 'alues where'er possible.

    4?

    http://play.golang.org/p/c86oXzfQOt
  • 8/13/2019 Go by Example

    51/91

    'efer

    &efer is used to ensure that a function call is performed later in a program s execution,usuall$ for purposes of cleanup. defer isoften used where e.g. ensure and finall7 would be used in other languages.

    package mainimport "fmt"import "os"

    "uppose we wanted to create a file, write toit, and then close when we re done. Here show we could do that with defer .

    func main() {

    (mmediatel$ after getting a file ob

  • 8/13/2019 Go by Example

    52/91

    Collection Functions

    #e often need our programs to perform operations on collections ofdata, like selecting all items thatsatisf$ a gi'en predicate or mappingall items to a new collection with acustom function.

    (n some languages it s idiomatic touse generic data structures andalgorithms. Go does not supportgenerics5 in Go it s common to

    pro'ide collection functions if andwhen the$ are specificall$ needed for$our program and data t$pes.

    Here are some example collectionfunctions for slices of strings . +oucan use these examples to build $ourown functions. %ote that in somecases it ma$ be clearest to (*s

  • 8/13/2019 Go by Example

    53/91

    Deturns true if all of the strings inthe slice satisf$ the predicate f .

    func Ill(*s

  • 8/13/2019 Go by Example

    54/91

    $ go run collection-functions.go+falsetruefalse

  • 8/13/2019 Go by Example

    55/91

  • 8/13/2019 Go by Example

    56/91

    Oeplace f%o0plit

  • 8/13/2019 Go by Example

    57/91

    Strin# Formattin#

    Go offers excellent support for stringformatting in the printf tradition. Here aresome examples of common string formattingtasks.

    package mainimport "fmt"import "os"t7pe point struct { ># 7 int}func main() {

    Go offers se'eral printing 'erbs designedto format general Go 'alues. or example,this prints an instance of our point struct.

    p point{!# +} fmt.Printf("6*Cn"# p)

    (f the 'alue is a struct, the 6 * 'ariant willinclude the struct s field names.

    fmt.Printf("6 *Cn"# p)

    !he 6T* 'ariant prints a Go s$ntaxrepresentation of the 'alue, i.e. the source

    code snippet that would produce that 'alue.

    fmt.Printf("6T*Cn"# p)

    !o print the t$pe of a 'alue, use 6L . fmt.Printf("6LCn"# p)

    ormatting booleans is straight-forward. fmt.Printf("6tCn"# true)

    !here are man$ options for formattingintegers. 8se 6d for standard, base-&?formatting.

    fmt.Printf("6dCn"# !+&)

    !his prints a binar$ representation. fmt.Printf("6bCn"# ! )

    !his prints the character corresponding tothe gi'en integer.

    fmt.Printf("6cCn"# &&)

    6> pro'ides hex encoding. fmt.Printf("6>Cn"# , )

    !here are also se'eral formatting options forfloats. or basic decimal formatting use 6f .

    fmt.Printf("6fCn"# 1.5)

    6e and 6K format the float in :slightl$different 'ersions of; scientific notation.

    fmt.Printf("6eCn"# !+& %%%%%.%) fmt.Printf("6KCn"# !+& %%%%%.%)

    47

    http://play.golang.org/p/qayRuqXHym
  • 8/13/2019 Go by Example

    58/91

    or basic string printing use 6s . fmt.Printf("6sCn"# "C"stringC"")

    !o double-1uote strings as in Go source, use6D.

    fmt.Printf("6DCn"# "C"stringC"")

    0s with integers as seen earlier, 6> rendersthe string in base-&6, with two outputcharacters per b$te of input.

    fmt.Printf("6>Cn"# "he> this")

    !o print a representation of a pointer, use 6p . fmt.Printf("6pCn"# 'p)

    #hen formatting numbers $ou will oftenwant to control the width and precision ofthe resulting figure. !o specif$ the width of

    an integer, use a number after the 6 in the'erb. )$ default the result will be right-

  • 8/13/2019 Go by Example

    59/91

  • 8/13/2019 Go by Example

    60/91

    "e#ular Expressions

    Go offers built-in support for regularexpressions . Here are some examplesof common regexp-related tasks inGo.

    package mainimport "b7tes"import "fmt"import "rege>p"func main() {

    !his tests whether a pattern matchesa string.

    match# A rege>p.Natch0tring("p(("peachpunch"))

    !he Ill 'ariants of these functionsappl$ to all matches in the input, not

  • 8/13/2019 Go by Example

    61/91

    !hese Ill 'ariants are a'ailable forthe other functions we saw abo'e aswell.

    fmt.Println(r.JindIll0tring0ubmatchEnde>( "peach punch pinch"# -!))

    @ro'iding a non-negati'e integer asthe second argument to thesefunctions will limit the number ofmatches.

    fmt.Println(r.JindIll0tring("peach punchpinch"# +))

    Our examples abo'e had stringarguments and used names likeNatch0tring . #e can also pro'idep package can also beused to replace subsets of stringswith other 'alues.

    fmt.Println(r.OeplaceIll0tring("a peach"#"2fruitB"))

    !he Junc 'ariant allows $ou totransform matched text with a gi'enfunction.

    in pressions.gotruetruepeach6&

    http://golang.org/pkg/regexp/http://golang.org/pkg/regexp/
  • 8/13/2019 Go by Example

    62/91

    S,)

    Go offers built-in support for "O%encoding and decoding, including toand from built-in and custom datat$pes.

    package mainimport "encoding/3son"import "fmt"import "os"

    #e ll use these two structs todemonstrate encoding and decoding ofcustom t$pes below.

    t7pe Oesponse! struct { Page int Jruits

  • 8/13/2019 Go by Example

    63/91

    %ow let s look at decoding "O% datainto Go 'alues. Here s an example fora generic data structure.

    b7t

  • 8/13/2019 Go by Example

    64/91

    '{!

  • 8/13/2019 Go by Example

    65/91

    (ime

    Go s offers extensi'e support for times anddurations5 here are some examples.

    package mainimport "fmt"import "time"func main() { p fmt.Println

    #e ll start b$ getting the current time. now time.8ow() p(now)

    +ou can build a time struct b$ pro'iding the$ear, month, da$, etc. !imes are alwa$sassociated with a @ocation , i.e. time one.

    then time.?ate( +%%5# !!# ! # +%# & # ,1#,!&1 +& # time. LM) p(then)

    +ou can extract the 'arious components ofthe time 'alue as expected.

    p(then.Vear()) p(then.Nonth()) p(then.?a7()) p(then.;our()) p(then.Ninute()) p(then.0econd()) p(then.8anosecond()) p(then.@ocation())

    !he Bonda$-"unda$ 9eekda7 is alsoa'ailable.

    p(then.9eekda7())

    !hese methods compare two times, testing ifthe first occurs before, after, or at the sametime as the second, respecti'el$.

    p(then.Hefore(now)) p(then.Ifter(now)) p(then.KDual(now))

    !he 0ub methods returns a ?uration representing the inter'al between two times.

    diff now.0ub(then) p(diff)

    #e can compute the length of the durationin 'arious units.

    p(diff.;ours()) p(diff.Ninutes()) p(diff.0econds()) p(diff.8anoseconds())

    +ou can use Idd to ad'ance a time b$ agi'en duration, or with a - to mo'e

    backwards b$ a duration.

    p(then.Idd(diff)) p(then.Idd(-diff))}

    $ go run time.go+%!+-!%-&! !, ,% !&. 5& , %%%% LM+%%5-!!-! +% & ,1. ,!&1 +& %%%% LM+%%58o*ember!

    +%&,1

    64

    http://play.golang.org/p/NxuQTlVA2l
  • 8/13/2019 Go by Example

    66/91

    ,!&1 +&LMLuesda7truefalsefalse

    +,15!h!,m!,.! ++ &s+,15!.+, +% !1,+!!.,,& ,+,+& !!!+1e %5.&+%1,!,! ++ e %5&+%1,!,! ++ &+%!+-!%-&! !, ,% !&. 5& , %%%% LM+%% -!+-%, %! !5 &.,%5!+% %%%% LM

    %ext we ll look at the related idea of timerelati'e to the 8nix epoch.

    66

  • 8/13/2019 Go by Example

    67/91

    Epoch

    0 common re1uirement in programs isgetting the number of seconds, milliseconds,or nanoseconds since the 8nix epoch . Here show to do it in Go.

    package mainimport "fmt"import "time"func main() {

    8se time.8ow with ni> or ni>8ano to getelapsed time since the 8nix epoch inseconds or nanoseconds, respecti'el$.

    now time.8ow() secs now. ni>() nanos now. ni>8ano() fmt.Println(now)

    %ote that there is no ni>Nillis , so to getthe milliseconds since epoch $ou ll need tomanuall$ di'e from nanoseconds.

    millis nanos / !%%%%%% fmt.Println(secs) fmt.Println(millis) fmt.Println(nanos)

    +ou can also con'ert integer seconds ornanoseconds since the epoch into thecorresponding time .

    fmt.Println(time. ni>(secs# %)) fmt.Println(time. ni>(%# nanos))}

    $ go run epoch.go

    +%!+-!%-&! ! !& ,1.+5+&1 %%%% LM!&,! %%%&1!&,! %%%&1+5+!&,! %%%&1+5+&1 %%%+%!+-!%-&! ! !& ,1 %%%% LM+%!+-!%-&! ! !& ,1.+5+&1 %%%% LM

    %ext we ll look at another time-related task>time parsing and formatting.

    67

    http://en.wikipedia.org/wiki/Unix_timehttp://play.golang.org/p/3jXHvYbLUzhttp://en.wikipedia.org/wiki/Unix_time
  • 8/13/2019 Go by Example

    68/91

  • 8/13/2019 Go by Example

    69/91

    6=

  • 8/13/2019 Go by Example

    70/91

    "andom )umbers

    Go s math/rand package pro'ides pseudorandom number generation.

    package mainimport "fmt"import "math/rand"func main() {

    or example, rand.Entn returns arandom int n, % 2 n 2 !%% .

    fmt.Print(rand.Entn(!%%)# "#") fmt.Print(rand.Entn(!%%)) fmt.Println()

    rand.Jloat returns a float f ,%.% 2 f 2 !.% . fmt.Println(rand.Jloat ())

    !his can be used to generate randomfloats in other ranges, for example,.% 2 f: 2 !%.% .

    fmt.Print((rand.Jloat ()F,) ,# "#") fmt.Print((rand.Jloat () F ,) ,) fmt.Println()

    !o make the pseudorandomgenerator deterministic, gi'e it awell-known seed.

    s! rand.8ew0ource( +) r! rand.8ew(s!)

    Call the resulting rand.0ource

  • 8/13/2019 Go by Example

    71/91

    )umber $arsin#

    @arsing numbers from strings is a basic but common task in man$ programs5 here s how to do it in Go.

    package main

    !he built-in package strcon* pro'ides the number parsing.

    import "strcon*"import "fmt"

    func main() {

    #ith ParseJloat , this tells how

    man$ bits of precision to parse.

    f# A strcon*.ParseJloat("!.+& "# ) fmt.Println(f)

    or ParseEnt , the % means infer the base from the string. re1uires thatthe result fit in 62 bits.

    i# A strcon*.ParseEnt("!+&"# %# ) fmt.Println(i)

    ParseEnt will recogni e hex-formatted numbers.

    d# A strcon*.ParseEnt("%>!c1"# %# ) fmt.Println(d)

    0 Parse int is also a'ailable. u# A strcon*.Parse int(" 15"# %# ) fmt.Println(u)

    Itoi is a con'enience function for basic base-&? int parsing.

    k# A strcon*.Itoi("!&,") fmt.Println(k)

    @arse functions return an error on bad input.

    A# e strcon*.Itoi("wat") fmt.Println(e)}

    $ go run number-parsing.go!.+&!+&,15!&,

    strcon*.ParseEnt parsing "wat" in*alids7nta>

    %ext we ll look at another common parsing task> 8DAs.

    7&

    http://play.golang.org/p/N90EppECFk
  • 8/13/2019 Go by Example

    72/91

    0". $arsin#

    8DAs pro'ide a uniform wa$ tolocate resources . Here s how to parse 8DAs in Go.

    package mainimport "fmt"import "net/url"import "strings"func main() {

    #e ll parse this example 8DA,which includes a scheme,authentication info, host, port,

    path, 1uer$ params, and 1uer$fragment.

    s "postgres //user passYhost.com , &+/pathZk *Tf"

    @arse the 8DA and ensure thereare no errors.

    u# err url.Parse(s) if err nil { panic(err) }

    0ccessing the scheme isstraightforward.

    fmt.Println(u.0cheme)

    ser contains all authenticationinfo5 call sername andPassword on this for indi'idual'alues.

    fmt.Println(u. ser) fmt.Println(u. ser. sername()) p# A u. ser.Password() fmt.Println(p)

    !he ;ost contains both thehostname and the port, if present.0plit the ;ost manuall$ toextract the port.

    fmt.Println(u.;ost) h strings.0plit(u.;ost# " ") fmt.Println(hHere we extract the path and thefragment after the T.

    fmt.Println(u.Path) fmt.Println(u.Jragment)

    !o get 1uer$ params in a string ofk * format, use Oaw[uer7 . +oucan also parse 1uer$ params intoa map. !he parsed 1uer$ parammaps are from strings to slices ofstrings, so index into

  • 8/13/2019 Go by Example

    73/91

    userpasshost.com , &+host.com, &+/path

    fk *map

  • 8/13/2019 Go by Example

    74/91

    SH 1 Hashes

    S'() hashes are fre1uentl$ used tocompute short identities for binar$ or text blobs. or example, the git re'ision controls$stem uses "H0&s extensi'el$ to identif$'ersioned files and directories. Here s howto compute "H0& hashes in Go.

    package main

    Go implements se'eral hash functions in'arious cr7pto/F packages.

    import "cr7pto/sha!"import "fmt"

    func main() { s "sha! this string"

    !he pattern for generating a hash issha!.8ew() , sha!.9rite(b7tes) , thensha!.0um( format'erb to con'ert a hash results to a hexstring.

    fmt.Println(s) fmt.Printf("6>Cn"# bs)}

    Dunning the program computes the hashand prints it in a human-readable hexformat.

    $ go run sha!-hashes.gosha! this stringcf+&df++% d55a fbe! 5e&eba%&,e &&b ,d5

    +ou can compute other hashes using asimilar pattern to the one shown abo'e. orexample, to compute B 4 hashes importcr7pto/md, and use md,.8ew() .

    %ote that if $ou need cr$ptographicall$secure hashes, $ou should carefull$research hash strength I

    72

    http://en.wikipedia.org/wiki/SHA-1http://git-scm.com/http://git-scm.com/http://en.wikipedia.org/wiki/Cryptographic_hash_functionhttp://play.golang.org/p/YUaWWEeB4Uhttp://en.wikipedia.org/wiki/SHA-1http://git-scm.com/http://git-scm.com/http://en.wikipedia.org/wiki/Cryptographic_hash_function
  • 8/13/2019 Go by Example

    75/91

    74

  • 8/13/2019 Go by Example

    76/91

  • 8/13/2019 Go by Example

    77/91

    "eadin# Files

    Deading and writing files are basictasks needed for man$ Go programs.irst we ll look at some examples ofreading files.

    package mainimport ( "bufio" "fmt" "io" "io/ioutil" "os")

    Deading files re1uires checking mostcalls for errors. !his helper willstreamline our error checks below.

    func check(e error) { if e nil { panic(e) }}func main() {

    @erhaps the most basic file readingtask is slurping a file s entirecontents into memor$.

    dat# err ioutil.OeadJile("/tmp/dat") check(err) fmt.Print(string(dat))

    +ou ll often want more control o'erhow and what parts of a file are read.or these tasks, start b$ Rpen ing afile to obtain an os.Jile 'alue.

    f# err os.Rpen("/tmp/dat")

    Dead some b$tes from the beginningof the file. 0llow up to 4 to be read

    but also note how man$ actuall$were read.

    b! make(

  • 8/13/2019 Go by Example

    78/91

    0eek(%# %) accomplishes this.

    !he bufio package implements a buffered reader that ma$ be useful both for its efficienc$ with man$small reads and because of theadditional reading methods it

    pro'ides.

    r bufio.8ewOeader(f)

    b # err r .Peek(,) check(err) fmt.Printf(", b7tes 6sCn"# string(b ))

    Close the file when $ou re done:usuall$ this would be scheduledimmediatel$ after Rpen ing withdefer ;.

    f.Mlose()

    }

    $ echo "hello" B /tmp/dat$ echo "go" BB /tmp/dat$ go run reading-files.gohellogo, b7tes hello+ b7tes Y go+ b7tes Y go, b7tes hello

    %ext we ll look at writing files.

    79

  • 8/13/2019 Go by Example

    79/91

    Writin# Files

    #riting files in Go follows similar patterns to the ones we saw earlierfor reading.

    package mainimport ( "bufio" "fmt" "io/ioutil" "os")func check(e error) { if e nil { panic(e) }}func main() {

    !o start, here s how to dump a string:or

  • 8/13/2019 Go by Example

    80/91

    wrote 5 b7tes

    !hen check the contents of thewritten files.

    $ cat /tmp/dat!hellogo$ cat /tmp/dat+some

    writesbuffered

    %ext we ll look at appl$ing some ofthe file (3O ideas we 'e

  • 8/13/2019 Go by Example

    81/91

    .ine Filters

    0 line filter is a common t$pe of programthat reads input on stdin, processes it, andthen prints some deri'ed result to stdout.grep and sed are common line filters.

    Here s an example line filter in Go thatwrites a capitali ed 'ersion of all input text.+ou can use this pattern to write $our ownGo line filters.

    package main

    import ( "bufio" "fmt" "io" "os" "strings")func main() {

    #rapping the unbuffered os.0tdin with a buffered reader gi'es us a con'enientOead0tring method that we ll use to readinput line-b$-line.

    rdr bufio.8ewOeader(os.0tdin) out os.0tdout

    Oead0tring returns the next string fromthe input up to the gi'en separator b$te. #egi'e the newline b$te :Cn: as our separatorso we ll get successi'e input lines.

    for { switch line# err rdr.Oead0tring(:Cn:)4 err {

    (f the read succeeded :the read err is nil;,write out out the uppercased line. Check foran error on this write as we do on the read.

    case nil ucl strings.Lo pper(line) if A# err out.9rite0tring(ucl)4 err nil { fmt.Jprintln(os.0tderr#"error "# err) os.K>it(!) }

    !he KRJ error is expected when we reachthe end of input, so exit gracefull$ in thatcase.

    case io.KRJ os.K>it(%)

    Otherwise there s a problem5 print the errorand exit with non- ero status.

    default fmt.Jprintln(os.0tderr#"error "# err) os.K>it(!) } }}

    !o tr$ out our line filter, first make a file$ echo :hello: B /tmp/lines$ echo :filter: BB /tmp/lines

    9&

    http://play.golang.org/p/OSS71nSpkV
  • 8/13/2019 Go by Example

    82/91

  • 8/13/2019 Go by Example

    83/91

    Command*.ine Fla#s

    "ommand-line flags are a common wa$ tospecif$ options for command-line programs.or example, in wc -l the -l is a command-line flag.

    package main

    Go pro'ides a flag package supporting basic command-line flag parsing. #e ll usethis package to implement our examplecommand-line program.

    import "flag"import "fmt"

    func main() {

    )asic flag declarations are a'ailable forstring, integer, and boolean options. Here wedeclare a string flag word with a default'alue "foo" and a short description. !hisflag.0tring function returns a string

    pointer :not a string 'alue;5 we ll see how touse this pointer below.

    wordPtr flag.0tring("word"#"foo"# "a string")

    !his declares numb and fork flags, using asimilar approach to the word flag.

    numbPtr flag.Ent("numb"# +# "anint")

    boolPtr flag.Hool("fork"# false#"a bool")

    (t s also possible to declare an option thatuses an existing 'ar declared elsewhere inthe program. %ote that we need to pass in a

    pointer to the flag declaration function.

    *ar s*ar string flag.0tring]ar('s*ar# "s*ar"#"bar"# "a string *ar")

    Once all flags are declared, callflag.Parse() to execute the command-line

    parsing.

    flag.Parse()

    Here we ll

  • 8/13/2019 Go by Example

    84/91

    'alues for all flags.

    numb fork trues*ar flagtail

  • 8/13/2019 Go by Example

    85/91

    En-ironment Variables

    En'ironment 'ariables are a uni'ersalmechanism for con'e$ing configurationinformation to 8nix programs . Aet s look athow to set, get, and list en'ironment'ariables.

    package mainimport "os"import "strings"import "fmt"func main() {

    !o set a ke$3'alue pair, use os.0eten* . !oget a 'alue for a ke$, use os.Qeten* . !hiswill return an empt$ string if the ke$ isn t

    present in the en'ironment.

    os.0eten*("JRR"# "!") fmt.Println("JRR "#os.Qeten*("JRR")) fmt.Println("HIO "#os.Qeten*("HIO"))

    8se os.Kn*iron to list all ke$3'alue pairs inthe en'ironment. !his returns a slice ofstrings in the form XKV *alue . +ou canstrings.0plit them to get the ke$ and'alue. Here we print all the ke$s.

    fmt.Println() for A# e range os.Kn*iron() { pair strings.0plit(e# " ") fmt.Println(pair

  • 8/13/2019 Go by Example

    86/91

    Spawnin# $rocesses

    "ometimes our Go programs need to spawnother, non-Go processes. or example, thes$ntax highlighting on this site isimplemented b$ spawning a p7gmentiGe

    process from a Go program. Aet s look at afew examples of spawning processes fromGo.

    package mainimport "fmt"import "io/ioutil"import "os/e>ec"func main() {

    #e ll start with a simple command thattakes no arguments or input and ec.Mommand helper creates an obec.Mommand("date")

    .Rutput is another helper than handles thecommon case of running a command,

    waiting for it to finish, and collecting itsoutput. (f there were no errors, dateRut willhold b$tes with the date info.

    dateRut# err dateMmd.Rutput() if err nil { panic(err) } fmt.Println("B date") fmt.Println(string(dateRut))

    %ext we ll look at a slightl$ more in'ol'edcase where we pipe data to the external

    process on its stdin and collect the resultsfrom its stdout .

    grepMmd e>ec.Mommand("grep"#"hello")

    Here we explicitl$ grab input3output pipes,start the process, write some input to it, readthe resulting output, and finall$ wait for the

    process to exit.

    grepEn# A grepMmd.0tdinPipe() grepRut# A grepMmd.0tdoutPipe() grepMmd.0tart() grepEn.9rite(

  • 8/13/2019 Go by Example

    87/91

    %ote that when spawning commands weneed to pro'ide an explicitl$ delineatedcommand and argument arra$, 's. being ableto

    lsMmd e>ec.Mommand("bash"# "-c"#"ls -a -l -h") lsRut# err lsMmd.Rutput() if err nil { panic(err) }

    fmt.Println("B ls -a -l -h") fmt.Println(string(lsRut))}

    !he spawned programs return output that isthe same as if we had run them directl$ fromthe command-line.

    $ go run spawning-processes.goB date9ed Rct !% %5 ,& !! P?L +%!+

    B grep hellohello grepB ls -a -l -hdrw>r->r-> mark !& H Rct & ! +5 .drw>r->r-> 5! mark &.%X Rct & !+ ,% ..-rw-r--r-- ! mark !.&X Rct & ! +1spawning-processes.go

    97

  • 8/13/2019 Go by Example

    88/91

    Exec4in# $rocesses

    (n the pre'ious example we looked atspawning external processes . #e do thiswhen we need an external process accessibleto a running Go process. "ometimes we ec function.

    package mainimport "s7scall"import "os"import "os/e>ec"func main() {

    or our example we ll exec ls . Go re1uiresan absolute path to the binar$ we want toexecute, so we ll use e>ec.@ookPath to findit :probabl$ /bin/ls ;.

    binar7# lookKrr e>ec.@ookPath("ls") if lookKrr nil { panic(lookKrr) }

    K>ec re1uires arguments in slice form :asapposed to one big string;. #e ll gi'e ls a

    few common arguments. %ote that the firstargument should be the program name.

    args ec also needs a set of en'ironment'ariables to use. Here we ec call. (f this call issuccessful, the execution of our process willend here and be replaced b$ the /bin/ls -a-l -h process. (f there is an error we ll get areturn 'alue.

    e>ecKrr s7scall.K>ec(binar7#args# en*) if e>ecKrr nil { panic(e>ecKrr) }

    }

    #hen we run our program it is replaced b$ls .

    $ go run e>ecing-processes.gototal !drw>r->r-> mark !& H Rct & ! +5 .drw>r->r-> 5! mark &.%X Rct & !+ ,% ..-rw-r--r-- ! mark !.&X Rct & ! +1e>ecing-processes.go

    %ote that Go does not offer a classic 8nixfork function. 8suall$ this isn t an issuethough, since starting goroutines, spawning

    processes, and exec ing processes co'ersmost use cases for fork .

    99

    https://gobyexample.com/spawning-processeshttp://en.wikipedia.org/wiki/Exec_(operating_system)http://en.wikipedia.org/wiki/Exec_(operating_system)https://gobyexample.com/environment-variableshttps://gobyexample.com/environment-variableshttp://play.golang.org/p/iEAD2cYC-hhttps://gobyexample.com/spawning-processeshttp://en.wikipedia.org/wiki/Exec_(operating_system)https://gobyexample.com/environment-variableshttps://gobyexample.com/environment-variables
  • 8/13/2019 Go by Example

    89/91

    9=

  • 8/13/2019 Go by Example

    90/91

    Si#nals

    "ometines we d like our Go programs tointelligentl$ handle 8nix signals . orexample, we might want a ser'er togracefull$ shutdown when it recei'es a0EQLKON, or a command-line tool to stop

    processing input if it recei'es a 0EQE8L .Here s how to handle signals in Go withchannels.

    package mainimport "fmt"import "os"import "os/signal"import "s7scall"func main() {

    Go signal notification works b$ sendingos.0ignal 'alues on a channel. #e ll createa channel to recei'e these notifications:we ll also make one to notif$ us when the

    program can exit.;

    sigs make(chan os.0ignal# !) done make(chan bool# !)

    signal.8otif7 registers the gi'en channelto recei'e notifications of the specifiedsignals.

    signal.8otif7(sigs# s7scall.0EQE8L#s7scall.0EQLKON)

    !his goroutine executes a blocking recei'efor signals. #hen it gets one it ll print it outand then notif$ the program that it canfinish.

    go func() { sig 2-sigs fmt.Println() fmt.Println(sig) done 2- true }()

    !he program will wait here until it gets theexpected signal :as indicated b$ the

    goroutine abo'e sending a 'alue on done ;and then exit.

    fmt.Println("awaiting signal") 2-done fmt.Println("e>iting")}

    #hen we run this program it will blockwaiting for a signal. )$ t$ping ctrl-M :which the terminal shows as ^M; we cansend a 0EQE8L signal, causing the programto print interrupt and then exit.

    $ go run signals.goawaiting signal^Minterrupte>iting

    =?

    http://en.wikipedia.org/wiki/Unix_signalhttp://play.golang.org/p/d42wO1q1ohhttp://en.wikipedia.org/wiki/Unix_signal
  • 8/13/2019 Go by Example

    91/91

    Exit

    8se os.K>it to immediatel$ exit with agi'en status.

    package mainimport "fmt"import "os"func main() {

    defer s will not be run when using os.K>it ,so this fmt.Println will ne'er be called.

    defer fmt.Println(" ")

    Exit with status /.

    os.K>it(&)}

    %ote that unlike e.g. C, Go does not use aninteger return 'alue from main to indicateexit status. (f $ou d like to exit with a non-ero status $ou should use os.K>it .

    (f $ou run e>it.go using go run , the exitwill be picked up b$ go and printed.

    $ go run e>it.goe>it status &

    )$ building and executing a binar$ $ou cansee the status in the terminal.

    $ go build e>it.go$ ./e>it

    $ echo $Z&

    %ote that the from our program ne'er got printed.

    http://play.golang.org/p/CDiAh9SXRM