17. 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
36. What is "Polymorphism"
The provision of a single interface to entities of different types
Via Generics, Overloading and/or Subtyping
— wikipedia
36
37. Go’s approach
• Go avoided 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
40. Interfaces in Go
type Rental struct {
name string
feePerDay float64
period int
}
func (r Rental) Cost() float64 {
return r.feePerDay * float64(r.period)
}
40
43. 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
44. 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
45. 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
46. Go is object-oriented!
• Go is object-based
• Code reuse via Composition
• Polymorphism via interface
46
49. 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
50. 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
54. 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
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
67. Caching
• RDBMS can be slow
• Using Redis is good, but fault tolerance is too hard.
• Solution: Timeout waiting
67
68. 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