oroutine
http://127.0.0.1:3999/concurrency/1
doc
https://golang.org/pkg/sync/
go demo
Goroutines run in the same address space, so access to shared memory must be synchronized. The sync package provides useful primitives, although you won’t need them much in Go as there are other primitives. (See the next slide.)
package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") }
channel
Channels are a typed conduit through which you can send and receive values with the channel operator, <-.
this channel will be block until double side ready.
普通管道 没有缓冲区, 会被 job 两端 阻塞.
直到 双方数据准备好.
使用中 需要 避免死锁.
fatal error: all goroutines are asleep - deadlock!
package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // send sum to c } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // receive from c fmt.Println(x, y, x+y) }
Buffered Channels
缓冲管道.
Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.
package main import "fmt" func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 fmt.Println(<-ch) fmt.Println(<-ch) }
range and close channel
range 会尝试 持续的 获取 管道 输出, 无输出 时 也会 阻塞, 直到 管道 关闭 才会结束
package main import ( "fmt" ) func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } func main() { c := make(chan int, 10) go fibonacci(cap(c), c) for i := range c { fmt.Println(i) } }
judge channel state
Another note: Channels aren’t like files; you don’t usually need to close them. Closing is only necessary when the receiver must be told there are no more values coming, such as to terminate a range loop.
管道 并不像 文件一样. 没有必要 关闭.
除非 接收端 使用了 range , 或者 处于 某种 设计 .
Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.
注意 只有 发送端 应该 关闭 管道, 因为 接受者 关闭 管道 后, 会导致 发送端 引发 异常, ok 探测 也能在 接收端 进行.
v, ok := <-ch if !ok { panic("channel have be closed") }
select on channel
The select statement lets a goroutine wait on multiple communication operations.
select 让go 协程, 在 多个 通信 操作 之间 等待.
A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready.
select 会阻塞, 直到 其中一个 通信 操作 可以 进行.
如果 有 多个 通信 操作 可以执行, 他会 随机选择 一个 去执行.
package main import "fmt" func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return } } } func main() { c := make(chan int) quit := make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<-c) } quit <- 0 }() fibonacci(c, quit) }
default in select channel
The default case in a select is run if no other case is ready.
当 左右 case 都无法 触发 的 时候, default 会被 执行.
Use a default case to try a send or receive without blocking:
当你 不想 被 通信 锁死的 时候, 请选择 default
package main import ( "fmt" "time" ) func main() { tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) for { select { case <-tick: fmt.Println("tick.") case <-boom: fmt.Println("BOOM!") return default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } } }