Introduction to Go
-
Upload
jaehue-jang -
Category
Technology
-
view
723 -
download
0
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