Go
장재휴
1
Agenda
1. 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&
pragmatism
5
얼마나?
6
• C#: 79
• PHP: 65
• Java: 50
• Ruby: 41
• C: 37
• Javascript: 34
• Python: 29
• Go: 25
7
• 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
• Convention
11
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
attributes
A 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 Declaration
type Item struct {
name string
price float64
quantity int
}
// Method Declaration
func (t Item) Cost() float64 {
return t.price * float64(t.quantity)
}
// In Action
func main() {
shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3}
fmt.Println("cost: ", shirt.Cost())
}
20
Object in Go
// Type Declaration
type Items []Item
// Method Declaration
func (ts Items) Cost() float64 {
var c float64
for _, t := range ts {
c += t.Cost()
}
return c
}
// In Action
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}
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 Go
Object-oriented
Language?
24
What is "Inheritance"
Provides reuse of existing objects
Classes are created in hierarchies
Inheritance 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 Declaration
type Item struct {
name string
price float64
quantity int
}
type DiscountItem struct {
Item
discountRate float64
}
// In Action
func 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 Declaration
func (t Item) Cost() float64 {
return t.price * float64(t.quantity)
}
// In Action
func 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 Declaration
func (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 Action
func 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 Methods
func (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 types
Via 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 Go
type Rental struct {
name string
feePerDay float64
period int
}
func (r Rental) Cost() float64 {
return r.feePerDay * float64(r.period)
}
40
Interfaces in Go
type 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
// Items
type 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" package
type 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)
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 Interface
func 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 is
independently executing function.
go f()
go f(x, y, ...)
• It's not a thread
• Very lightweight
• A goroutine has its own stack
• A goroutine runs concurrently
50
51
Goroutine example
func 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 // define
var ch1 chan<- string // send only
var ch2 <-chan string // receive only
• Create
ch = make(chan string) // create
• Use
ch <- "msg" // send value on channel
m := <-ch // receive value from channel
54
Communicating goroutines
func 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 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 {
/* ... */
}
64
Run concurrently
errc := 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, <- errc
if 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 variance
func 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

Introduction to Go

  • 1.
  • 2.
    Agenda 1. Introduction 2. OOPin Go 3. Concurrency in Go 4. Real world Go 2
  • 3.
    Simple can beharder than complex 3
  • 4.
  • 5.
  • 6.
  • 7.
    • C#: 79 •PHP: 65 • Java: 50 • Ruby: 41 • C: 37 • Javascript: 34 • Python: 29 • Go: 25 7
  • 8.
    • 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
  • 9.
    • Java: 780 •Scala: 191 • Go: 51 9
  • 10.
    없다 • ❌ while •❌ ++i ⭕ i++ • ❌ sum += i++ • ❌ enum • ❌ class • ❌ inheritance • ❌ generic • ❌ exception 10
  • 11.
    있다 • Pointer ❗ •Duck typing ❗ • Mandatory ❗ • Code organization • Formatting • Indentation • Convention 11
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
    What is "ObjectOriented" A language is usually considered object-based if it includes the basic capabilities for an object: identity, properties, and attributes A language is considered object-oriented if it is object-based and also has the capability of polymorphism and inheritance — wikipedia 17
  • 18.
  • 19.
    What is an"Object" An object is an abstract data type that has state(data) and behavior(code) — wikipedia 19
  • 20.
    Object in Go //Type Declaration type Item struct { name string price float64 quantity int } // Method Declaration func (t Item) Cost() float64 { return t.price * float64(t.quantity) } // In Action func main() { shirt := Item{name: "Men's Slim-Fit Shirt", price: 25000, quantity: 3} fmt.Println("cost: ", shirt.Cost()) } 20
  • 21.
    Object in Go //Type Declaration type Items []Item // Method Declaration func (ts Items) Cost() float64 { var c float64 for _, t := range ts { c += t.Cost() } return c } // In Action 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} fmt.Println("cost of shirt: ", shirt.Cost()) fmt.Println("cost of shoes: ", shoes.Cost()) fmt.Println("total cost: ", items.Cost()) } 21
  • 22.
    Object in Go typequantity 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
  • 23.
  • 24.
  • 25.
    What is "Inheritance" Providesreuse of existing objects Classes are created in hierarchies Inheritance passes knowledge down! — wikipedia 25
  • 26.
    Inheritance is notgood! You should avoid implementation inheritance whenever possible. — James Gosling 26
  • 27.
    Go's approach • Goavoided inheritance • Go strictly follows the Composition over inheritance principle 27
  • 28.
    What is Composition •Provides reuse of Objects • One object is declared by containing other objects • Composition pulls knowledge into another 28
  • 29.
  • 30.
    Composition in Go //Type Declaration type Item struct { name string price float64 quantity int } type DiscountItem struct { Item discountRate float64 } // In Action func 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
  • 31.
    Call Method ofEmbedded Type type DiscountItem struct { Item discountRate float64 } // Method Declaration func (t Item) Cost() float64 { return t.price * float64(t.quantity) } // In Action func 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
  • 32.
    Method Overriding // MethodDeclaration func (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 Action func 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
  • 33.
    // Type Declaration(embedded field) type Items []Item type Order struct { Items taxRate float64 } // Overriding Methods func (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
  • 34.
    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
  • 35.
  • 36.
    What is "Polymorphism" Theprovision of a single interface to entities of different types Via Generics, Overloading and/or Subtyping — wikipedia 36
  • 37.
    Go’s approach • Goavoided subtyping & overloading • Go does not provide Generics • Polymorphism via interfaces 37
  • 38.
    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.
  • 40.
    Interfaces in Go typeRental struct { name string feePerDay float64 period int } func (r Rental) Cost() float64 { return r.feePerDay * float64(r.period) } 40
  • 41.
    Interfaces in Go typeCoster 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
  • 42.
    // Items type 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
  • 43.
    The Power ofInterface • Writer interface in standard "io" package type 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) 43
  • 44.
    The Power ofInterface • 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
  • 45.
    The Power ofInterface func 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
  • 46.
    Go is object-oriented! •Go is object-based • Code reuse via Composition • Polymorphism via interface 46
  • 47.
  • 48.
    Go's Concurrency is Easyto understand. Easy to use. You don't need to be an expert! 48
  • 49.
    Go's approach • InUNIX: processes connected by pipes find ~/go/src | grep _test.go$ | xargs wc -l • In Go: goroutines connected by channels 49
  • 50.
    Goroutine is independently executingfunction. go f() go f(x, y, ...) • It's not a thread • Very lightweight • A goroutine has its own stack • A goroutine runs concurrently 50
  • 51.
  • 52.
    Goroutine example func 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
  • 53.
  • 54.
    Channel-based communication • Define varch chan string // define var ch1 chan<- string // send only var ch2 <-chan string // receive only • Create ch = make(chan string) // create • Use ch <- "msg" // send value on channel m := <-ch // receive value from channel 54
  • 55.
    Communicating goroutines func 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
  • 56.
    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
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
    A Tour ofGo ⌘+C ⌘+V = ✌ 61
  • 62.
    Measure First • Rubyversion • Go version 62
  • 63.
    Excuting next jobwhile waiting 63
  • 64.
    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 { /* ... */ } 64
  • 65.
    Run concurrently errc :=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, <- errc if err1 != nil || err2 != nil || err3 != nil { /* ... */ } 65
  • 66.
  • 67.
    Caching • RDBMS canbe slow • Using Redis is good, but fault tolerance is too hard. • Solution: Timeout waiting 67
  • 68.
    Caching with controlvariance func 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
  • 69.
  • 70.
    Before and After •Ruby version • Go version 70
  • 71.