func main() {
c := make(chan int, 20)
go func() {
for i := 0; i < 10; i++ {
c <- i
}
close(c)
}()
// 当 c 被关闭后,取完里面的元素就会跳出循环
for x := range c {
fmt.Println(x)
}
}
多个 goroutine 同步响应
利用 close 广播
func main() {
c := make(chan struct{})
for i := 0; i < 5; i++ {
go do(c)
}
close(c)
}
func do(c <-chan struct{}) {
// 会阻塞直到收到 close
<-c
fmt.Println("hello")
}
非阻塞的 select
select 本身是阻塞的,当所有分支都不满足就会一直阻塞,如果想不阻塞,那么一个什么都不干的 default 分支是最好的选择
select {
case <-done:
return
default:
}
for{select{}} 终止
尽量不要用 break label 形式,而是把终止循环的条件放到 for 条件里来实现
for ok {
select {
case ch <- 0:
case <-done:
ok = false
}
}
channel 特性
基础特性
| 操作 | 值为 nil 的 channel | 被关闭的 channel | 正常的 channel |
|---|---|---|---|
| close | panic | panic | 成功关闭 |
| c<- | 永远阻塞 | panic | 阻塞或成功发送 |
| <-c | 永远阻塞 | 永远不阻塞 | 阻塞或成功接收 |
happens-before 特性
-
无缓冲时,接收 happens-before 发送
任何情况下,发送 happens-before 接收
close happens-before 接收
参考
https://go101.org/article/channel.html
https://golang.org/doc/effective_go.html#channels
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易采站长站。









