從底層實現上來看,通道只是乙個佇列。同步模式下,傳送和接收雙方配對,然後直接複製資料給對方。如配對失敗,則置入等待佇列,直到另一方出現後才會喚醒。非同步模式搶奪的則是資料緩衝槽。傳送方要求有空槽可供寫入,而接收方則要求有緩衝資料可讀。需求不符時,同樣加入等待佇列,直到有另一方寫入資料或騰出空槽後被喚醒。
內建函式 cap 和 len 返回緩衝區大小和當前已緩衝數量;而對於同步通道則都返回0,據此可判斷通道是同步還是非同步。
package main
import
"fmt"
func
main()
輸出:
0 03 2
對於 closed 或 nil 通道,傳送和接收操作都有相應規則:
單向通道
儘管可用 make 建立單向通道,但那沒有任何意義。通常使用型別轉換來獲取單向通道,並分別賦予操作雙方。
package main
import
("sync"
)func
main()
}()go
func()
}() wg.
wait()
}
輸出為:01
2同樣, close 不能用於接收端。
package main
func
main()
選擇
如果要同時處理多個通道,可選用 select 語句。它會隨機選擇乙個可用通道做收發操作。
package main
import
"sync"
func
main()
if!ok
println
(name, x)}}
()gofunc()
}}()
wg.wait()
}
輸出:
b 0a 1
b 20
a 3b 40
a 5b 60
b 70
b 80
b 90
如果要等全部通道訊息處理結束,可將已完成通道設定為 nil。這樣它就會被阻塞,不再被 select 選中。
package main
import
"sync"
func
main()
println
("a"
, x)
case x, ok :=
<- b:
if!ok
println
("b"
, x)
}if a ==
nil&& b ==
nil}}(
)gofunc()
}()go
func()
}() wg.
wait()
}
輸出為:
a 0b 0
a 1b 10
a 2b 20
b 30
b 40
同步
將 mutex 作為匿名欄位時,相關方法必須實現為 pointer-receiver,否則會因複製導致鎖機制失效。
package main
import
("sync"
"time"
)type data struct
func
(d data)
test
(s string)}
func
main()
()gofunc()
()wg.
wait()
}
輸出為:
write 0
read 0
write 1
read 1
write 2
read 2
write 3
read 3
read 4
write 4
鎖失效,將 receiver 型別改為 *data 後正常。也可用嵌入 *mutex 來避免複製問題,但那需要專門初始化。
mutex 不支援遞迴鎖,即便在同一 goroutine 下也會導致死鎖。
package main
import
"sync"
func
main()
m.unlock()
}
go 通道 go語言通道channel
通過使用通道,在多個goroutine傳送和接受共享的資料,達到資料同步的目的。通道,他有點像在兩個routine之間架設的管道,乙個goroutine可以往這個管道裡塞資料,另外乙個可以從這個管道裡取資料,有點類似於我們說的佇列。宣告乙個通道很簡單,我們使用chan關鍵字即可,除此之外,還要指定通...
GO 通道的關閉
並不是往通道裡放多少次資料,就必須取多次少資料的 之前的例子都是放3次取3次,放10次取10次 我們可以做乙個操作,當子協程沒有新放入的時候,主協程不再去取,這就是關閉通道 package main import fmt channel並不像檔案那樣需要經常去關閉它,只有當你確實沒有任何傳送資料了,...
Go 緩衝通道
語法結構 cap為容量 ch make chan type,cap 通道是非同步的,是一種在被建立時就被開闢了能儲存乙個或者多個值的通道。這種型別並不要求傳送與接收同時進行。只要緩衝區有未使用空間用於傳送資料,或還包含可以接收的資料,那麼其通訊就會無阻塞地進行。只有在通道中沒有要接收的值時,接收動作...