共计 762 个字符,预计需要花费 2 分钟才能阅读完成。
咱们来看下两端代码:
代码段 1
func main() {channels := make([]chan int, 10)
for i := 0; i < 10; i++ {go func(ch chan int) {time.Sleep(time.Second)
ch <- 1
}(channels[i])
}
for ch := range channels {fmt.Println("Routine", ch, "quit!")
}
fmt.Println("完结")
}
猜测下这下面会打印什么后果。
代码段 2
func main() {ch := make(chan int, 10)
for i := 0; i < 10; i++ {go func() {ch <- i}()}
for range ch {<-ch}
fmt.Println(1111)
}
猜测下代码 2 会打印什么后果。
本人能够运行下,
代码段 1 会失常运行,代码段 2 会死锁,纳尼,不一样吧,确实就是不一样。
请留神: 代码段 1 channels 是一个切片类型哦。
#### 总结一下:
channel 反对 for range 的形式进行遍历,须要留神两个细节。
1. 在遍历时,如果 channel 没有敞开,则回呈现 deadlock 的谬误。
2. 在遍历时,如果 channel 曾经敞开,则会失常遍历数据,遍历完后,就会退出遍历。
3. 对于 nil channel,无论收发都会被阻塞。
4. 写完 chan 之后肯定要敞开 close chan,否则主协程读的时候,会产生被阻塞。
select 语句中除 default 外,每个 case 操作一个 channel,要么读要么写。
select 语句中除 default 外,各 case 执行程序是随机的。
select 语句中如果没有 default 语句, 则会阻塞期待任一 case。
select 语句中读操作要判断是否胜利读取,敞开的 channel 也能够读取.
遍历 chan 与 遍历切片类型是不一样的。
正文完