go lang tutorial

58
Go Lang Tutorial Wei-Ning Huang (AZ)

Upload: wei-ning-huang

Post on 19-Aug-2014

5.510 views

Category:

Education


2 download

DESCRIPTION

這是 Code & Beer Meetup 的第一次 Talk 投影片,主題為 Go Lang 的 Tutorial。

TRANSCRIPT

Page 1: Go Lang Tutorial

Go Lang TutorialWei-Ning Huang (AZ)

Page 2: Go Lang Tutorial

About the Speaker

● Wei-Ning Huang (a.k.a: AZ)● Open source / Freelance Developer● Found out more at http://azhuang.me

Page 3: Go Lang Tutorial

About the Slide

● License: ● Most of the code examples come from

official Go Tour and Effective Go

Page 4: Go Lang Tutorial

Outline

● History● Why Go?● Library Support● Tutorial

○ Variable Declaration○ Function Declaration○ Flow Control○ Method and Interface○ Goroutines

● Conclusion● References

Page 5: Go Lang Tutorial

Go!

Page 6: Go Lang Tutorial

History

● From Google!○ The guys at Plan 9 from Bell Labs

● Current Version 1.1.2, still being actively developed

Page 7: Go Lang Tutorial

Why Go!

● Fast○ Almost as fast as C○ Faster than C in some cases

● A small language● Statically-typed● Garbage Collection● Easy to write/learn● Reflection

Page 8: Go Lang Tutorial

How fast is Go?

From Computer Language Benchmark Game

Page 9: Go Lang Tutorial

Who use Go?

● Google, of course● Google App Engine also supports Go!

Page 10: Go Lang Tutorial

Library Support

● A lot of built-in support including:○ Containers: container/heap, container/list○ Web server: net/http○ Cryptography: crypto/md5, crypto/sha1○ Compression: compress/gzip○ Database: database/sql

Page 11: Go Lang Tutorial

Third-Party Libraries

● Gorilla: Web Framework● go-qt: Qt binding for Go● go-gtk3: Gtk3 binding for Go● go-opengl: OpenGL binding for Go● go:ngine: Go 3D Engine● mgo: MongoDB binding for go

Tons more at:https://code.google.com/p/go-wiki/wiki/Projects

Page 12: Go Lang Tutorial

Hello World!

package main

import "fmt"

func main() {fmt.Println("Hello, 世界")

}

$ go run hello_word.goHello, 世界

Page 13: Go Lang Tutorial

Using Packagepackage main

import ( "fmt" "math/rand")

func main() { fmt.Println("My favorite number is", rand.Intn(10))}

You can also import package with separated lineimport "fmt"import "math/rand"

Page 14: Go Lang Tutorial

● In Go, a name is exported if it begins with capital letter. That is, you should use

instead of

Exported Names

fmt.Println("My favorite number is", rand.Intn(10))

fmt.println("My favorite number is", rand.Intn(10))

Page 15: Go Lang Tutorial

Variablespackage main

import "fmt"

var x, y, z int

func main() { var c, python, java = true, false, "no!"

haskell, racket, sml := true, true, false

fmt.Println(x, y, z, c, python, java, haskell, racket, sml)}

type can be omitted, since compiler can guess it from the initializer

using the := construct, we can omit the var keyword and type!

Page 16: Go Lang Tutorial

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

var c complex128 = 1 + 2i

Page 17: Go Lang Tutorial

Constants

package main

import "fmt"

const Pi = 3.14

func main() { const World = "世界" fmt.Println("Hello", World) fmt.Println("Happy", Pi, "Day")

const Truth = true fmt.Println("Go rules?", Truth)}

Page 18: Go Lang Tutorial

Grouping Variable and Constants

var ( ToBe bool = false MaxInt uint64 = 1<<64 - 1 z complex128 = cmplx.Sqrt(-5 + 12i))

const ( Big = 1 << 100 Small = Big >> 99)

Page 19: Go Lang Tutorial

Functionspackage mainimport "fmt"

func add(x int, y int) int { return x + y}

func add_and_sub(x, y int) (int, int) { return x + y, x -y}

func main() { fmt.Println(add(42, 13))

a, b := add_and_sub(42, 13) fmt.Println(a, b)

}

paramter name type return type

x, y share the same type multiple return value

receiving multiple reutrn value

Page 20: Go Lang Tutorial

Functions - Named results

package main

import "fmt"

func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return}

func main() { fmt.Println(split(17))}

Page 21: Go Lang Tutorial

Functions are First Class Citizens

func main() {

hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) }

fmt.Println(hypot(3, 4))}

Functions in Go are first class citizens, which means that you can pass it around like values.

create a lambda(anonymous) function and assign it to a variable

Page 22: Go Lang Tutorial

Closures

func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum }}

Go uses lexical closures, which means a function is evaluated in the environment where it is defined.

sum is accessible inside the anonymous function!

Page 23: Go Lang Tutorial

For loopfunc main() { sum := 0 for i := 0; i < 10; i++ { sum += i } for ; sum < 1000; { sum += sum } for sum < 10000 { sum += sum } fmt.Println(sum)

for { }}

Go does not have while loop!while loops are for loops!

Infinite loop!

similar to C but without parentheses

Page 24: Go Lang Tutorial

Condition: Ifpackage main

import ( "fmt")

func main() { a := 10 if a > 1 { fmt.Println("if true") } if b := 123 * 456; b < 10000 { fmt.Println("another one, but with short statement") }}

short statement, b is lives only inside if block

Page 25: Go Lang Tutorial

Condition: Switch

func main() { fmt.Print("Go runs on ") switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: // freebsd, openbsd, // plan9, windows... fmt.Printf("%s.", os) }}

Just like if, can have short statement

Switch cases evaluate cases from top to bottom, stopping when a case succeeds.

Page 26: Go Lang Tutorial

Switch Without Condition

func main() { t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") }}

Like writing long if/else chains

no condition

Page 27: Go Lang Tutorial

Structs

package main

import "fmt"

type Vertex struct { X int Y int}

func main() { v := Vertex{1, 2} v.X = 4 fmt.Println(v.X)}

A struct is a collection of fields.Struct fields are accessed using a dot.

Page 28: Go Lang Tutorial

Structspackage main

import "fmt"

type Vertex struct { X int Y int}

func main() { v := Vertex{1, 2} v.X = 4 p := &v fmt.Println(v.X, p.X)}

p is a pointer to v, which has type *Vertex

Use dot to access field of a pointer

Page 29: Go Lang Tutorial

The new Function

package main

import "fmt"

type Vertex struct { X, Y int}

func main() { v := new(Vertex) fmt.Println(v) v.X, v.Y = 11, 9 fmt.Println(v)}

The expression new(T) allocates a zeroed T value and returns a pointer to it.

v has type: *Vertex

Page 30: Go Lang Tutorial

Slices

func main() { p := []int{2, 3, 5, 7, 11, 13} fmt.Println("p ==", p) fmt.Println("p[1:4] ==", p[1:4]) // [3 5 7] fmt.Println("p[:3] ==", p[:3]) // [2 3 5] fmt.Println("p[4:] ==", p[4:]) // [11 13] for i := 0; i < len(p); i++ { fmt.Printf("p[%d] == %d\n", i, p[i]) } var z []int if z == nil { fmt.Println("nil value") }}

A slice points to an array of values and also includes a length.The zero value of a slice is nil

empty slice: nil

Page 31: Go Lang Tutorial

Making Slices

func main() { a := make([]int, 5) printSlice("a", a) b := make([]int, 0, 5) printSlice("b", b)}func printSlice(s string, x []int) { fmt.Printf("%s len=%d cap=%d %v\n", s, len(x), cap(x), x)}

Use the make function to create slices.make(type, length, capacity)

a len=5 cap=5 [0 0 0 0 0]b len=0 cap=5 []

Page 32: Go Lang Tutorial

Array V.S. Slicesfunc main() { var array = [...]string{"a", "b", "c"} var slice = []string{"a", "b", "c"} fmt.Printf("%T\n", array) fmt.Printf("%T\n", slice)

//array = append(array, array...) // Won't compile! slice = append(slice, slice...) fmt.Println(slice)}

[3]string[]string[a b c a b c]

Page 33: Go Lang Tutorial

Maps

import "fmt"

type Vertex struct { Lat, Long float64}

var m map[string]Vertexfunc main() { m = make(map[string]Vertex) m["Bell Labs"] = Vertex{ 40.68433, -74.39967, } fmt.Println(m["Bell Labs"])}

● A map maps keys to values.● Maps must be created with make (not new) before use; the nil

map is empty and cannot be assigned to.

Page 34: Go Lang Tutorial

Maps Literals

var m = map[string]Vertex{ "Bell Labs": Vertex{ 40.68433, -74.39967, }, "Google": Vertex{ 37.42202, -122.08408, },}

var m2 = map[string]Vertex{ "Bell Labs": {40.68433, -74.39967}, "Google": {37.42202, -122.08408}}

map[key_type]value_type{key1: value1, key2: value2 …}

Can omit type name

Page 35: Go Lang Tutorial

Mutating Maps

m := make(map[string]int)m["Answer"] = 42

Assigning

m, ok := m["Answer"]if ok { fmt.Println("key exists!")}

Testing if a key exists

delete(m, "Answer")

Deleting an element

Page 36: Go Lang Tutorial

Iterating through Slices or Maps

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}var m = map[string]int{"a": 1, "b": 2}

func main() { for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) } for k, v := range m { fmt.Printf("%s: %d\n", k, v) }}

Use the range keyword

Page 37: Go Lang Tutorial

The _ Variable

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}var m = map[string]int{"a": 1, "b": 2}

func main() { for _, v := range pow { fmt.Printf("%d\n", v) } for _, v := range m { fmt.Printf("%d\n", v) }}

Go won’t let you compile you declare some variable but didn’t use it.In this case, you can assign it to _ to indicate that it will not be used.

We don’t use index here, assign it to _.

We don’t use key here, assign it to _.

Page 38: Go Lang Tutorial

Go: Objects without Class

● No class, use interfaces instead● No inheritance, use embedding instead

Page 39: Go Lang Tutorial

Method Declaration

type Vertex struct { X, Y float64}

func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y)}

func main() { v := &Vertex{3, 4} fmt.Println(v.Abs())}

Basically look like functions, but with extra receiver declaration before function name.

Page 40: Go Lang Tutorial

Method Declaration (cont’d)

func (t time.Time) bla() string { return t.LocalTime().String()[0:5]}

You may be tempted to declare new method on existing type, like monkey patching in Python or Ruby.

cannot define new methods on non-local type time.Time

type MyTime time.Timefunc (t MyTime) bla() string { return t.LocalTime().String()[0:5]}

The correct way is to create a type synonym then define method on it.

Page 41: Go Lang Tutorial

Interfaces

type Abser interface { Abs() float64}type MyFloat float64

func (f MyFloat) Abs() float64 { if f < 0 { return float64(-f) } return float64(f)}

● An interface type is defined by a set of methods.● A value of interface type can hold any value that implements

those methods.● Interfaces are satisfied implicitly

○ capture idioms and patterns after the code is being written

Page 42: Go Lang Tutorial

type Vertex struct { X, Y float64}func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y)}func main() { var a Abser f := MyFloat(-math.Sqrt2) v := Vertex{3, 4}

a = f // a MyFloat implements Abser a = &v // a *Vertex implements Abser a = v // a Vertex, does NOT implement Abser fmt.Println(a.Abs())}

Interfaces (cont’d)

Page 43: Go Lang Tutorial

Interfaces (cont’d)● Interfaces are infact like static-checked duck typing!● When I see a bird that walks like a duck and swims like a duck

and quacks like a duck, I call that bird a duck.

Page 44: Go Lang Tutorial

package main

import "fmt"

type World struct{}

func (w *World) String() string { return "世界"}

func main() { fmt.Printf("Hello, %s\n", new(World))}

Interfaces: Another Example

% go run hello.goHello, 世界

Page 45: Go Lang Tutorial

package fmt// Stringer is implemented by any value that has a String method,// which defines the ``native'' format for that value.// The String method is used to print values passed as an operand// to any format that accepts a string or to an unformatted printer// such as Print.type Stringer interface{ String() string}

Interfaces: Another Example (cont’d)fmt.Stringer

Naming Convention: An interface with single method should be name as method name with “er” as postfix

Page 46: Go Lang Tutorial

Errors

type MyError struct { When time.Time What string}

func (e *MyError) Error() string { return fmt.Sprintf("at %v, %s", e.When, e.What)}

type error interface { Error() string}

Errors in go are defined as interface:

Defining new error type

Page 47: Go Lang Tutorial

Embedding

type Car struct { wheelCount int }

func (car Car) numberOfWheels() int { return car.wheelCount}

type Ferrari struct { Car //anonymous field Car}func main() { f := Ferrari{Car{4}} fmt.Println("A Ferrari has this many wheels: ", f.numberOfWheels())}

Sort of “Inheritance” in OOP.

Page 48: Go Lang Tutorial

Goroutines

func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) }}

func main() { go say("world") say("hello")}

A goroutine is a lightweight thread managed by the Go runtime.

Page 49: Go Lang Tutorial

Channels

ch := make(chan int)

ch <- v // Send v to channel ch.v := <-ch // Receive from ch, and // assign value to v.

● Channels are a typed conduit through which you can send and receive values.

● By default, sends and receives block until the other side is ready.

● Channels can be buffered. Provide the buffer length as the second argument to make to initialize a buffered channel:

● Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.

ch := make(chan int, 100)

Page 50: Go Lang Tutorial

Channels (cont’)func sum(a []int, c chan int) { sum := 0 for _, v := range a { sum += v } c <- sum // send sum to c}

func main() { a := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(a[:len(a)/2], c) go sum(a[len(a)/2:], c) x, y := <-c, <-c // receive from c

fmt.Println(x, y, x+y)}

Page 51: Go Lang Tutorial

Closing a Channel

close(ch) // close the channel

v, ok := <-ch

if !ok { fmt.Println("channel closed")}

● A sender can close a channel to indicate that no more values will be sent.

● Receivers can test whether a channel has been closed by assigning a second parameter to the receive expression

Page 52: Go Lang Tutorial

Select

func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return } }}

The select statement lets a goroutine wait on multiple communication operations.

Page 53: Go Lang Tutorial

Defer, Panic, and Recover

func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f", r) } }()

ofs, err := os.Create("/dev/stdout") if err == nil { fmt.Fprintf(ofs, "Hello, 世界\n") } else { panic(err) } defer ofs.Close()}

A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns.

Page 54: Go Lang Tutorial

Generics?

Why does Go not have generic types?

Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.

Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it. Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.

From Go website:

Page 55: Go Lang Tutorial

Type Switchfunc anything(data interface{}) { switch data.(type) { case int: fmt.Println("int") case string: fmt.Println("string") case fmt.Stringer: fmt.Println("Stringer") default: fmt.Println("whatever...") }}

type World struct{}

func (w *World) String() string { return "世界"}

func main() { anything("a string") anything(42) anything(new(World)) anything(make([]int, 5))}

stringintStringerwhatever...

Page 56: Go Lang Tutorial

Type Assertionfunc anything(data interface{}) { s, ok := data.(fmt.Stringer) if ok { fmt.Printf("We got Stringer: %T\n", s) } else { fmt.Println("bah!") }}

type World struct{}

func (w *World) String() string { return "世界"}

func main() { anything("a string") anything(42) anything(new(World)) anything(make([]int, 5))}

bah!bah!We got Stringer: *main.Worldbah!

Page 57: Go Lang Tutorial

Conclusion

● Go is a fast, small, easy-to-learn language● Actively developed by Google● Tons of third-party libraries● Learn it by using it!

Page 58: Go Lang Tutorial

References

● Go Official Tutorial [website]● Effective Go [website]● Advanced Go Concurrency Patterns [Slide, Video]● Go and Rust — objects without class [lwn.net]