SlideShare a Scribd company logo
Introduction to Go 
GDG Korea DevFair 2014 
장재휴 
Developer, Purpleworks
Simple can be harder than complex 
단 순 함 은 복 잡 함 보 다 어 렵 다 . 
생 각 을 명 쾌 하 게 해 단 순 하 게 만 드 려 면 굉 장 히 노 력 해 야 한 다 . 
하 지 만 결 국 그 럴 가 치 가 있 다 . 일 단 단 순 함 에 도 달 하 면 , 산 을 움 직 일 수 있 기 때 문 이 다 .
Agenda 
What is Go 
OOP in Go 
Concurrency in Go 
Real world Go
What is 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)
What is go 
A modern, general purpose language. 
open source 
Statically typed languages 
Feel dynamically 
concurrents 
garbage-collected 
efficient 
simply
OOP in Go
1. Object via struct and method 
No Classes. No "Objects" 
But Go is object-based
Object in Go 
package main 
import "fmt" 
// Type Declaration (Struct) 
type Rect struct { 
width int 
height int 
} 
// Declaring a Method 
func (r *Rect) Area() int { 
return r.width * r.height 
} 
// In Action 
func main() { 
r := Rect{width: 10, height: 5} 
fmt.Println("area: ", r.Area()) 
} Run
Object in Go II 
// Type Declaration (built-in type) 
type Rects []Rect 
// Declaring a Method 
func (rs Rects) Area() int { 
var a int 
for _, r := range rs { 
a += r.Area() 
} 
return a 
} 
// In Action 
func 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
2. Code reuse 
No Inheritance 
Composition over inheritance principle
Composition in Go 
// Type Declaration (Struct) 
type Address struct { 
Number, Street, City, State string 
} 
// Embedding Types 
type Person struct { 
Name string 
Address 
} 
func main() { 
// Declare using Composite Literal 
p := Person{ 
Name: "Steve", 
Address: Address{Number: "13", Street: "Main", City: "Gotham", State: "NY"}, 
} 
fmt.Println(p) 
fmt.Println(p.Address) 
} Run
Composition in Go II 
// Declaring a Method 
func (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() 
} 
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
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"
Interfaces in Go 
type Rect struct { 
width int 
height int 
} 
type Rects []Rect 
func (r Rect) Area() int { 
return r.width * r.height 
} 
func (rs Rects) Area() int { 
var a int 
for _, r := range rs { 
a += r.Area() 
} 
return a 
} 
// Interface Declaration 
type Shaper interface { 
Area() int 
}
Interfaces in Go II 
// Interface Declaration 
type Shaper interface { 
Area() int 
} 
// Using Interface as Param Type 
func Describe(s Shaper) { 
fmt.Println("Area is:", s.Area()) 
} 
// In Action 
func main() { 
r := Rect{width: 10, height: 5} 
x := Rect{width: 7, height: 10} 
rs := Rects{r, x} 
Describe(r) 
Describe(x) 
Describe(rs) 
} Run
The Power of Interface 
Writer interface in standard "io" package 
// http://godoc.org/io#Writer 
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)
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) 
} 
} Run
The Power of Interface 
The http.ResponseWriter can be used for 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:]) 
}) 
fmt.Println("start listening on port 4000") 
http.ListenAndServe(":4000", nil) 
} Run 
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)
Concurrency in Go
What is concurrency 
Composition of independently executing computations. 
It is not parallelism.
Go's Concurrency is 
Easy to understand. 
Easy to use. 
You don't need to be an expert!
Go's approach 
In UNIX: processes connected by pipes: 
find ~/go/src | grep _test.go$ | xargs wc -l 
In Go: goroutines connected by channels
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
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
Fundamentals #2 - Channel-based communication 
Channel allow goroutines to exchange information and synchronize. 
Define 
chan int 
chan<- string // send-only channel 
<-chan T // receive-only channel 
Create channel 
ch = make(chan int) 
Use 
ch <- 1 // send value 1 on channel ch 
x = <-ch // receive a value from channel ch
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
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
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."
Real world Go
mixquare.com 
Microchats for everyone 
Instantly create a channel any topic, location or event
Message Flow
Action of message processing worker 
1. save message to datastore 
2. fetch channel information 
3. fetch user information 
4. publish
Measure First 
ruby version 
go version
Concurrency 
RPC-bound jobs are very common 
Excuting next job while waiting
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 { 
/* ... */ 
}
Concurrency III 
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 { /* ... */ }
Result(Concurrency) 
baseline 
concurrency
Caching 
Using SQL can be slow 
Using redis is good, but fault tolerance is too hard. 
Solution: Timeout waiting
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 
}
Result(Caching) 
concurrency 
caching
Before and After 
ruby version 
go version
Conclusion
Go is... not so great 
Go is young language
Thank you 
장재휴 
Developer, Purpleworks 
jaehue@jang.io (mailto:jaehue@jang.io)

More Related Content

Introduction to go

  • 1. Introduction to Go GDG Korea DevFair 2014 장재휴 Developer, Purpleworks
  • 2. Simple can be harder than complex 단 순 함 은 복 잡 함 보 다 어 렵 다 . 생 각 을 명 쾌 하 게 해 단 순 하 게 만 드 려 면 굉 장 히 노 력 해 야 한 다 . 하 지 만 결 국 그 럴 가 치 가 있 다 . 일 단 단 순 함 에 도 달 하 면 , 산 을 움 직 일 수 있 기 때 문 이 다 .
  • 3. Agenda What is Go OOP in Go Concurrency in Go Real world Go
  • 5. 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)
  • 6. What is go A modern, general purpose language. open source Statically typed languages Feel dynamically concurrents garbage-collected efficient simply
  • 8. 1. Object via struct and method No Classes. No "Objects" But Go is object-based
  • 9. Object in Go package main import "fmt" // Type Declaration (Struct) type Rect struct { width int height int } // Declaring a Method func (r *Rect) Area() int { return r.width * r.height } // In Action func main() { r := Rect{width: 10, height: 5} fmt.Println("area: ", r.Area()) } Run
  • 10. Object in Go II // Type Declaration (built-in type) type Rects []Rect // Declaring a Method func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a } // In Action func 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
  • 11. 2. Code reuse No Inheritance Composition over inheritance principle
  • 12. Composition in Go // Type Declaration (Struct) type Address struct { Number, Street, City, State string } // Embedding Types type Person struct { Name string Address } func main() { // Declare using Composite Literal p := Person{ Name: "Steve", Address: Address{Number: "13", Street: "Main", City: "Gotham", State: "NY"}, } fmt.Println(p) fmt.Println(p.Address) } Run
  • 13. Composition in Go II // Declaring a Method func (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() } 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
  • 14. 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"
  • 15. Interfaces in Go type Rect struct { width int height int } type Rects []Rect func (r Rect) Area() int { return r.width * r.height } func (rs Rects) Area() int { var a int for _, r := range rs { a += r.Area() } return a } // Interface Declaration type Shaper interface { Area() int }
  • 16. Interfaces in Go II // Interface Declaration type Shaper interface { Area() int } // Using Interface as Param Type func Describe(s Shaper) { fmt.Println("Area is:", s.Area()) } // In Action func main() { r := Rect{width: 10, height: 5} x := Rect{width: 7, height: 10} rs := Rects{r, x} Describe(r) Describe(x) Describe(rs) } Run
  • 17. The Power of Interface Writer interface in standard "io" package // http://godoc.org/io#Writer 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)
  • 18. 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) } } Run
  • 19. The Power of Interface The http.ResponseWriter can be used for 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:]) }) fmt.Println("start listening on port 4000") http.ListenAndServe(":4000", nil) } Run 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)
  • 21. What is concurrency Composition of independently executing computations. It is not parallelism.
  • 22. Go's Concurrency is Easy to understand. Easy to use. You don't need to be an expert!
  • 23. Go's approach In UNIX: processes connected by pipes: find ~/go/src | grep _test.go$ | xargs wc -l In Go: goroutines connected by channels
  • 24. 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
  • 25. 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
  • 26. Fundamentals #2 - Channel-based communication Channel allow goroutines to exchange information and synchronize. Define chan int chan<- string // send-only channel <-chan T // receive-only channel Create channel ch = make(chan int) Use ch <- 1 // send value 1 on channel ch x = <-ch // receive a value from channel ch
  • 27. 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
  • 28. 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
  • 29. 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."
  • 31. mixquare.com Microchats for everyone Instantly create a channel any topic, location or event
  • 33. Action of message processing worker 1. save message to datastore 2. fetch channel information 3. fetch user information 4. publish
  • 34. Measure First ruby version go version
  • 35. Concurrency RPC-bound jobs are very common Excuting next job while waiting
  • 36. 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 { /* ... */ }
  • 37. Concurrency III 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 { /* ... */ }
  • 39. Caching Using SQL can be slow Using redis is good, but fault tolerance is too hard. Solution: Timeout waiting
  • 40. 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 }
  • 42. Before and After ruby version go version
  • 44. Go is... not so great Go is young language
  • 45. Thank you 장재휴 Developer, Purpleworks jaehue@jang.io (mailto:jaehue@jang.io)