Introduction to Go

Post on 15-Jan-2017

723 views 0 download

Transcript of Introduction to Go

Go장재휴

1

Agenda1. Introduction

2. OOP in Go

3. Concurrency in Go

4. Real world Go

2

Simple can be harder than complex

3

1 Introduction

4

Go is...

simplicity&

pragmatism5

얼마나?

6

• C#: 79

• PHP: 65

• Java: 50

• Ruby: 41

• C: 37

• Javascript: 34

• Python: 29

• Go: 257

• C#(4.0) https://msdn.microsoft.com/en-us/library/x53a06bb(v=vs.140).aspx

• PHP(5.6.12) http://php.net/manual/en/reserved.keywords.php

• Java(SE 8) http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9

• Ruby(2.2.2) http://ruby-doc.org/core-2.2.2/doc/keywords_rdoc.html

• C(ANSI C) https://en.wikipedia.org/wiki/Csyntax#Reservedkeywords

• Javascript(ECMAScript 6) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Keywords

• Python(2.3.5) http://docs.python.org/release/2.3.5/ref/keywords.html

• Go(1.5) https://golang.org/ref/spec#Keywords

8

• Java: 780

• Scala: 191

• Go: 51

9

없다• ❌ while

• ❌ ++i ⭕ i++

• ❌ sum += i++

• ❌ enum

• ❌ class

• ❌ inheritance

• ❌ generic

• ❌ exception

10

있다• Pointer ❗

• Duck typing ❗

• Mandatory ❗

• Code organization

• Formatting

• Indentation

• Convention11

Readability !

12

Static vs. Dynamic

13

Static + Dynamic !

14

!!

15

2 OOP in Go

16

What is "Object Oriented"A language is usually considered object-based if it includes the basic capabilities for an object: identity, properties, and attributesA language is considered object-oriented if it is object-based and also has the capability of polymorphism and inheritance— wikipedia

17

Is Go Object-based Language?

18

What is an "Object"An object is an abstract data type that has state(data) and behavior(code)— wikipedia

19

Object in Go

// Type Declarationtype Item struct { name string price float64 quantity int}

// Method Declarationfunc (t Item) Cost() float64 { return t.price * float64(t.quantity)}

// In Actionfunc main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} fmt.Println("cost: ", shirt.Cost())}

20

Object in Go

// Type Declarationtype Items []Item

// Method Declarationfunc (ts Items) Cost() float64 { var c float64 for _, t := range ts { c += t.Cost() } return c}

// In Actionfunc main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} items := Items{shirt, shoes}

fmt.Println("cost of shirt: ", shirt.Cost()) fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("total cost: ", items.Cost())}

21

Object in Go

type quantity int

func (q quantity) greaterThan(i int) bool { return int(q) > i }

func (q *quantity) increment() { *q++ }

func (q *quantity) decrement() { *q-- }

func main() { q := quantity(3) q.increment() fmt.Printf("Is q(%d) greater than %d? %t \n", q, 3, q.greaterThan(3)) q.decrement() fmt.Printf("Is q(%d) greater than %d? %t \n", q, 3, q.greaterThan(3))}

22

Go is Object-based!

23

Is GoObject-oriented

Language?

24

What is "Inheritance"Provides reuse of existing objectsClasses are created in hierarchiesInheritance passes knowledge down!— wikipedia

25

Inheritance is not good!You should avoid implementation inheritance whenever possible.— James Gosling

26

Go's approach• Go avoided inheritance

• Go strictly follows the Composition over inheritance principle

27

What is Composition• Provides reuse of Objects

• One object is declared by containing other objects

• Composition pulls knowledge into another

28

29

Composition in Go

// Type Declarationtype Item struct { name string price float64 quantity int}

type DiscountItem struct { Item discountRate float64}

// In Actionfunc main() { shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} eventShoes := DiscountItem{ Item: Item{name: "Women's Walking Shoes", price: 50000, quantity: 3}, discountRate: 10.00, }

fmt.Println("shoes: ", shoes) fmt.Println("eventShoes: ", eventShoes)}

30

Call Method of Embedded Type

type DiscountItem struct { Item discountRate float64}

// Method Declarationfunc (t Item) Cost() float64 { return t.price * float64(t.quantity)}

// In Actionfunc main() { shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} eventShoes := DiscountItem{ Item: Item{name: "Women's Walking Shoes", price: 50000, quantity: 3}, discountRate: 10.00, }

fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("cost of eventShoes: ", eventShoes.Cost())}

31

Method Overriding

// Method Declarationfunc (t Item) Cost() float64 { return t.price * float64(t.quantity)}

func (t DiscountItem) Cost() float64 { return t.Item.Cost() * (1.0 - t.discountRate/100)}

// In Actionfunc main() { shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} eventShoes := DiscountItem{ Item: Item{name: "Women's Walking Shoes", price: 50000, quantity: 3}, discountRate: 10.00, }

fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("cost of eventShoes: ", eventShoes.Cost())}

32

// Type Declaration (embedded field)type Items []Item

type Order struct { Items taxRate float64}

// Overriding Methodsfunc (o Order) Cost() float64 { return o.Items.Cost() * (1.0 + o.taxRate/100)}

func main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} items := Items{shirt, shoes} order := Order{Items: items, taxRate: 10.00}

fmt.Println("cost of shirt: ", shirt.Cost()) fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("total cost: ", items.Cost()) fmt.Println("total cost(included Tax): ", order.Cost())}

33

func main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} shoes := Item{name: "Sports Shoes", price: 30000, quantity: 2} eventShoes := DiscountItem{ Item: Item{name: "Women's Walking Shoes", price: 50000, quantity: 3}, discountRate: 10.00, } items := Items{shirt, shoes, eventShoes} order := Order{Items: items, taxRate: 10.00}

fmt.Println("cost of shirt: ", shirt.Cost()) fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("cost of eventShoes: ", eventShoes.Cost()) fmt.Println("total cost: ", items.Cost()) fmt.Println("total cost(included Tax): ", order.Cost())}

34

Polymorphism

35

What is "Polymorphism"The provision of a single interface to entities of different typesVia Generics, Overloading and/or Subtyping— wikipedia

36

Go’s approach• Go avoided subtyping & overloading

• Go does not provide Generics

• Polymorphism via interfaces

37

Interfaces in Go• Interface is just set of methods

• Interface define behavior (duck typing)

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

38

39

Interfaces in Gotype Rental struct { name string feePerDay float64 period int}

func (r Rental) Cost() float64 { return r.feePerDay * float64(r.period)}

40

Interfaces in Gotype Coster interface { Cost() float64}

func DisplayCost(c Coster) { fmt.Println("cost: ", c.Cost())}

func main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} video := Rental{"Interstellar", 1000, 3}

fmt.Printf("[%s] ", shirt.name) DisplayCost(shirt) fmt.Printf("[%s] ", video.name) DisplayCost(video)}

41

// Itemstype Items []Coster

func main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} video := Rental{"Interstellar", 1000, 3, Days} eventShoes := DiscountItem{ Item{name: "Women's Walking Shoes", price: 50000, quantity: 3}, 10.00, } items := Items{shirt, video, eventShoes} order := Order{Items: items, taxRate: 10.00}

DisplayCost(shirt) DisplayCost(video) DisplayCost(eventShoes) DisplayCost(items) DisplayCost(order)}

42

The Power of Interface• Writer interface in standard "io" packagetype Writer interface { Write(p []byte) (n int, err os.Error)}

• Fprintln function in standard "fmt" packagefunc Fprintln(w io.Writer, a ...interface{}) (n int, err error)

43

The Power of Interface• In handle function, just write to io.Writer object

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

• 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) }}

44

The Power of Interfacefunc handle(w io.Writer, msg string) { fmt.Fprintln(w, msg)}

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

func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { handle(w, r.URL.Path[1:]) })

fmt.Println("start listening on port 4000") http.ListenAndServe(":4000", nil)}

45

Go is object-oriented!• Go is object-based

• Code reuse via Composition

• Polymorphism via interface

46

3 Concurrency in Go

47

Go's Concurrency is

Easy to understand.Easy to use.You don't need to be an expert!

48

Go's approach• In UNIX: processes connected by pipes

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

• In Go: goroutines connected by channels

49

Goroutine isindependently executing function.

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

• It's not a thread

• Very lightweight

• A goroutine has its own stack

• A goroutine runs concurrently50

51

Goroutine examplefunc main() { go long() go short() time.Sleep(3 * time.Second) // 3초 대기 fmt.Println("main 함수 종료", time.Now())}func long() { fmt.Println("long 함수 시작", time.Now()) time.Sleep(2500 * time.Millisecond) // 2.5초 대기 fmt.Println("long 함수 종료", time.Now())}

func short() { fmt.Println("short 함수 시작", time.Now()) time.Sleep(2000 * time.Millisecond) // 2초 대기 fmt.Println("short 함수 종료", time.Now())}

52

Channel

53

Channel-based communication• Define

var ch chan string // definevar ch1 chan<- string // send onlyvar ch2 <-chan string // receive only

• Create

ch = make(chan string) // create

• Use

ch <- "msg" // send value on channelm := <-ch // receive value from channel

54

Communicating goroutinesfunc main() { done := make(chan bool) go long(done) go short(done) <-done <-done fmt.Println("main 함수 종료", time.Now())}func long(done chan bool) { fmt.Println("long 함수 시작", time.Now()) time.Sleep(2500 * time.Millisecond) // 2.5초 대기 fmt.Println("long 함수 종료", time.Now()) done <- true}func short(done chan bool) { fmt.Println("short 함수 시작", time.Now()) time.Sleep(2000 * time.Millisecond) // 2초 대기 fmt.Println("short 함수 종료", time.Now()) done <- true}

55

Go's Concurrency is

• 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.

56

4 Real world Go

57

Messaging

58

59

Go60

A Tour of Go

⌘+C ⌘+V = ✌

61

Measure First• Ruby version

• Go version

62

Excuting next job while waiting

63

Run synchronouslyerr1 := msg.save()

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

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

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

64

Run concurrentlyerrc := make(chan error)

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

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

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

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

65

Result(Concurrency)• baseline

• concurrency

66

Caching• RDBMS can be slow

• Using Redis is good, but fault tolerance is too hard.

• Solution: Timeout waiting

67

Caching with control variancefunc fetchUser(id string) (*User, error) { var u *User var err error

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

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

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

68

Result(Caching)• concurrency

• caching

69

Before and After• Ruby version

• Go version

70

Conclusion

71