introduction to go

45
Introduction to Go GDG Korea DevFair 2014 장재휴 Developer, Purpleworks

Upload: jaehue-jang

Post on 12-Jul-2015

2.543 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Introduction to go

Introduction to GoGDG Korea DevFair 2014

장재휴Developer, Purpleworks

Page 2: Introduction to go

Simple can be harder than complex

단 순 함 은 복 잡 함 보 다 어 렵 다 . 생 각 을 명 쾌 하 게 해 단 순 하 게 만 드 려 면 굉 장 히 노 력 해 야 한 다 . 하 지 만 결 국 그 럴 가 치 가 있 다 . 일 단 단 순 함 에 도 달 하 면 , 산 을 움 직 일 수 있 기 때 문 이 다 .

Page 3: Introduction to go

Agenda

What is Go

OOP in Go

Concurrency in Go

Real world Go

Page 4: Introduction to go

What is Go

Page 5: Introduction to go

Why Go?

Statically typed languages ➔ Efficient vs Hard to write

Dynamic language ➔ Easy to use vs Slow

Speed vs Safety vs Ease to use

Concurrent programming is hard(thread, lock, mutex)

Page 6: Introduction to go

What is go

A modern, general purpose language.

open source

Statically typed languages

Feel dynamically

concurrents

garbage-collected

efficient

simply

Page 7: Introduction to go

OOP in Go

Page 8: Introduction to go

1. Object via struct and method

No Classes. No "Objects"

But Go is object-based

Page 9: Introduction to go

Object in Go

package main

import "fmt"

// Type Declaration (Struct)type Rect struct { width int height int}

// Declaring a Methodfunc (r *Rect) Area() int {func (r *Rect) Area() int { return r.width * r.height}

// In Actionfunc main() { r := Rect{width: 10, height: 5} fmt.Println("area: ", r.Area())fmt.Println("area: ", r.Area())} Run

Page 10: Introduction to go

Object in Go II

// Type Declaration (built-in type)type Rects []Recttype Rects []Rect

// Declaring a Methodfunc (rs Rects) Area() int {func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a}

// In Actionfunc main() { r := Rect{width: 10, height: 5} x := Rect{width: 7, height: 10} rs := Rects{r, x} fmt.Println("r's area: ", r.Area()) fmt.Println("x's area: ", x.Area()) fmt.Println("total area: ", rs.Area())} Run

Page 11: Introduction to go

2. Code reuse

No Inheritance

Composition over inheritance principle

Page 12: Introduction to go

Composition in Go

// Type Declaration (Struct)type Address struct { Number, Street, City, State string}

// Embedding Typestype Person struct { Name string AddressAddress}

func main() { // Declare using Composite Literal p := Person{ Name: "Steve", Address: Address{Number: "13", Street: "Main", City: "Gotham", State: "NY"},Address: Address{Number: "13", Street: "Main", City: "Gotham", State: "NY"}, } fmt.Println(p) fmt.Println(p.Address)} Run

Page 13: Introduction to go

Composition in Go II

// Declaring a Methodfunc (a *Address) String() string { return a.Number + " " + a.Street + "\n" + a.City + ", " + a.State + " " + "\n"}

func (p *Person) String() string { return p.Name + "\n" + p.Address.String()return p.Name + "\n" + p.Address.String()}

func main() { p := Person{ Name: "Steve", Address: Address{Number: "13", Street: "Main", City: "Gotham", State: "NY"}, } fmt.Println(p.String()) fmt.Println(p.Address.String())} Run

Page 14: Introduction to go

3. Polymorphism via interface

Interface is just set of methods

Interface define behavior (duck typing)

"If something can do this, then it can be used here"

Page 15: Introduction to go

Interfaces in Go

type Rect struct { width int height int}type Rects []Rect

func (r Rect) Area() int {func (r Rect) Area() int { return r.width * r.height}

func (rs Rects) Area() int {func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a}

// Interface Declarationtype Shaper interface {type Shaper interface { Area() intArea() int}}

Page 16: Introduction to go

Interfaces in Go II

// Interface Declarationtype Shaper interface { Area() int}

// Using Interface as Param Typefunc Describe(s Shaper) {func Describe(s Shaper) { fmt.Println("Area is:", s.Area())fmt.Println("Area is:", s.Area())}}

// In Actionfunc main() { r := Rect{width: 10, height: 5} x := Rect{width: 7, height: 10} rs := Rects{r, x}

Describe(r)Describe(r) Describe(x)Describe(x) Describe(rs)Describe(rs)} Run

Page 17: Introduction to go

The Power of Interface

Writer interface in standard "io" package

// http://godoc.org/io#Writertype Writer interface { Write(p []byte) (n int, err os.Error)}

Fprintln function in standard "fmt" package

func Fprintln(w io.Writer, a ...interface{}) (n int, err error)

Page 18: Introduction to go

The Power of Interface

In handle function, just write to io.Writer object

func handle(w io.Writer, msg string) { fmt.Fprintln(w, msg)}

The os.Stdout can be used for io.Writer.

func main() { msg := []string{"hello", "world", "this", "is", "an", "example", "of", "io.Writer"} for _, s := range msg { time.Sleep(100 * time.Millisecond) handle(os.Stdout, s)handle(os.Stdout, s) }} Run

Page 19: Introduction to go

The Power of Interface

The http.ResponseWriter can be used for io.Writer.

localhost:4000/hello-world (http://localhost:4000/hello-world)

localhost:4000/this-is-an-example-of-io.Writer (http://localhost:4000/this-is-an-example-of-io.Writer)

func handle(w io.Writer, msg string) { fmt.Fprintln(w, msg)}

func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { handle(w, r.URL.Path[1:])handle(w, r.URL.Path[1:]) }) fmt.Println("start listening on port 4000") http.ListenAndServe(":4000", nil)} Run

Page 20: Introduction to go

Concurrency in Go

Page 21: Introduction to go

What is concurrency

Composition of independently executing computations.

It is not parallelism.

Page 22: Introduction to go

Go's Concurrency is

Easy to understand.

Easy to use.

You don't need to be an expert!

Page 23: Introduction to go

Go's approach

In UNIX: processes connected by pipes:

find ~/go/src | grep _test.go$ | xargs wc -l

In Go: goroutines connected by channels

Page 24: Introduction to go

Fundamentals #1 - Goroutine

Independently executing function.

The go statement launches a function call as a goroutine

go f()go f(x, y, ...)

It's not a thread

Very lightweight

A goroutine has its own stack

A goroutine runs concurrently

Page 25: Introduction to go

Goroutine example

func f(msg string, delay time.Duration) { for { fmt.Println(msg) time.Sleep(delay) }}

func main() { go f("A--", 300*time.Millisecond) go f("-B-", 500*time.Millisecond) go f("--C", 1100*time.Millisecond) time.Sleep(10 * time.Second)} Run

Page 26: Introduction to go

Fundamentals #2 - Channel-based communication

Channel allow goroutines to exchange information and synchronize.

Define

chan intchan<- string // send-only channel<-chan T // receive-only channel

Create channel

ch = make(chan int)

Use

ch <- 1 // send value 1 on channel chx = <-ch // receive a value from channel ch

Page 27: Introduction to go

Communicating goroutines

func f(msg string, delay time.Duration, ch chan string) { for { ch <- msg time.Sleep(delay) }}

func main() { ch := make(chan string) go f("A--", 300*time.Millisecond, ch) go f("-B-", 500*time.Millisecond, ch) go f("--C", 1100*time.Millisecond, ch)

for i := 0; i < 100; i++ { fmt.Println(i, <-ch) }} Run

Page 28: Introduction to go

Communicating goroutines II

type Ball struct{ hits int }

func main() { table := make(chan *Ball) go player("ping", table) go player("pong", table)

table <- new(Ball) // game on; toss the ball time.Sleep(1 * time.Second) <-table // game over; grab the ball}

func player(name string, table chan *Ball) { for { ball := <-table ball.hits++ fmt.Println(name, ball.hits) time.Sleep(100 * time.Millisecond) table <- ball }} Run

Page 29: Introduction to go

Philosophy

Goroutines give the efficiency of an asynchronous model.

But you can write code in a synchronous style.

"Don’t communicate by sharing memory . Instead, share memory by communicating."

Page 30: Introduction to go

Real world Go

Page 31: Introduction to go

mixquare.com

Microchats for everyone

Instantly create a channel any topic, location or event

Page 32: Introduction to go

Message Flow

Page 33: Introduction to go

Action of message processing worker

1. save message to datastore 2. fetch channel information 3. fetch user information 4. publish

Page 34: Introduction to go

Measure First

ruby version

go version

Page 35: Introduction to go

Concurrency

RPC-bound jobs are very common

Excuting next job while waiting

Page 36: Introduction to go

Concurrency II

Run synchronously

err1 := msg.save()

c, err2 := msg.fetchChannel()msg.setChannel(c)

u, err3 := msg.fetchUser()msg.setUser(u)

if err1 != nil || err2 != nil || err3 != nil { /* ... */}

Page 37: Introduction to go

Concurrency III

Run concurrently

errc := make(chan error)

go func() {go func() { err := msg.save() errc <- errerrc <- err }()

go func() {go func() { c, err := msg.fetchChannel() msg.setChannel(c) errc <- errerrc <- err }()

go func() {go func() { u, err := msg.fetchUser() msg.setUser(u) errc <- errerrc <- err }()

err1, err2, err3 := <-errc, <-errc, <- errcerr1, err2, err3 := <-errc, <-errc, <- errc if err1 != nil || err2 != nil || err3 != nil { /* ... */ }

Page 38: Introduction to go

Result(Concurrency)

baseline

concurrency

Page 39: Introduction to go

Caching

Using SQL can be slow

Using redis is good, but fault tolerance is too hard.

Solution: Timeout waiting

Page 40: Introduction to go

Caching with control variance

func fetchUser(id string) (*User, error) { var u *User var err error

done := make(chan *User) go func() { u, _ := findFromRedis(id)u, _ := findFromRedis(id) done <- u }()

select {select { case u = <-done:case u = <-done: case <-time.After(REDIS_TIMEOUT * time.Millisecond):case <-time.After(REDIS_TIMEOUT * time.Millisecond): }}

if u == nil { u, err = findFromSql(id)u, err = findFromSql(id) if err != nil { return nil, err } saveToRedis(u)saveToRedis(u) } return u, nil}

Page 41: Introduction to go

Result(Caching)

concurrency

caching

Page 42: Introduction to go

Before and After

ruby version

go version

Page 43: Introduction to go

Conclusion

Page 44: Introduction to go

Go is... not so great

Go is young language

Page 45: Introduction to go

Thank you

장재휴Developer, [email protected] (mailto:[email protected])