我們可以看到 go 關鍵字很方便的就實現了併發程式設計。 上面的多個 goroutine 執行在同一個程序裡面,共享記憶體資料,不過設計上我們要遵循:不要透過共享來通訊,而要透過通訊來共享。
runtime.Gosched()表示讓 CPU 把時間片讓給別人,下次某個時候繼續恢復執行該 goroutine。
預設情況下,在 Go 1.5 將標識併發系統執行緒個數的 runtime.GOMAXPROCS 的初始值由 1 改為了執行環境的 CPU 核數。
但在 Go 1.5 以前排程器僅使用單執行緒,也就是說只實現了併發。想要發揮多核處理器的並行,需要在我們的程式中明確的呼叫 runtime.GOMAXPROCS(n) 告訴排程器同時使用多個執行緒。GOMAXPROCS 設定了同時執行邏輯程式碼的系統執行緒的最大數量,並回傳之前的設定。如果 n < 1,不會改變當前設定。
for i := range c能夠不斷的讀取 channel 裡面的資料,直到該 channel 被明確的關閉。上面程式碼我們看到可以明確的關閉 channel,生產者透過內建函式 close 關閉 channel。關閉 channel 之後就無法再發送任何資料了,在消費方可以透過語法v, ok := <-ch測試 channel 是否被關閉。如果 ok 回傳 false,那麼說明 channel 已經沒有任何資料並且已經被關閉。
記住應該在生產者的地方關閉 channel,而不是消費的地方去關閉它,這樣容易引起 panic
另外記住一點的就是 channel 不像檔案之類別的,不需要經常去關閉,只有當你確實沒有任何傳送資料了,或者你想明確的結束 range 迴圈之類別的
ch <- v // 傳送 v 到 channel ch.
v := <-ch // 從 ch 中接收資料,並賦值給 v
package main
import "fmt"
func sum(a []int, c chan int) {
total := 0
for _, v := range a {
total += v
}
c <- total // send total to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x + y)
}
ch := make(chan type, value)
package main
import "fmt"
func main() {
c := make(chan int, 2)//修改 2 為 1 就報錯,修改 2 為 3 可以正常執行
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
//修改為 1 報如下的錯誤:
//fatal error: all goroutines are asleep - deadlock!
package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 1, 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)
}
}
package main
import "fmt"
func fibonacci(c, quit chan int) {
x, y := 1, 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)
}
select {
case i := <-c:
// use i
default:
// 當 c 阻塞的時候執行這裡
}
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <- c:
println(v)
case <- time.After(5 * time.Second):
println("timeout")
o <- true
break
}
}
}()
<- o
}