模块 7 · 第 2 课(共 5)课程中的32/50~15 min
模块课程(2/5)
渠道:类型化沟通
通道是之间通信的惯用机制 协程。 Go 哲学 (Rob Pike):
“不要通过共享内存来交流;通过交流来共享内存。”
通道是一个类型化的 FIFO 队列,类型安全并且对于并发来说是安全的
使用。与 go 结合,它是 Go 的主要构建块
并发。
创建、发送、接收
Go
ch := make(chan int) // canale di int, unbuffered
go func() {
ch <- 42 // invia (può bloccare)
}()
v := <-ch // ricevi (può bloccare)
fmt.Println(v) // 42句法:
make(chan T)或make(chan T, N)用于缓冲。ch <- v发送。v := <-ch接收。v, ok := <-ch接收带有标志(ok = false如果通道关闭且为空)。
无缓冲:会合
无缓冲通道(容量 0)阻塞:
- 发送者,直到接收者准备好;
- 接收方,直到发送方准备就绪。
这是一个同步约会:用作“信号”或保证 价值已经交付。
缓冲:队列最多为 N
Go
ch := make(chan int, 3)
ch <- 1 // non blocca
ch <- 2 // non blocca
ch <- 3 // non blocca
ch <- 4 // BLOCCA: il buffer è pieno仅当缓冲区已满时发送方才会阻塞;仅接收器 当它是空的时候。
近距离和远距离
当没有更多值时,发送者关闭通道:
Go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch { // termina quando ch è chiuso E vuoto
fmt.Println(v)
}for range 在通道上迭代,直到通道关闭(并排空)。
这是“消耗所有到达的东西”的最干净的模式。
签名的方向性
函数参数可以限制方向:
Go
func producer(out chan<- int) { // solo invio
out <- 1
close(out)
}
func consumer(in <-chan int) { // solo ricezione
for v := range in {
fmt.Println(v)
}
}chan<- T = 仅发送,<-chan T = 仅接收。双向
通道 chan T 可以传递给任一通道(隐式转换)。它
提高清晰度并防止错误。
常见模式(预览)
- 工作池:N 个 goroutine 从
jobs <-chan T消费,在results chan<- R生产。 - 管道:通过通道连接的阶段。
- 完成信号:
chan struct{}通道关闭以发出“停止”信号。
Go
done := make(chan struct{})
go func() {
<-done // blocca finché qualcuno chiude done
cleanup()
}()
close(done) // segnale di stopchan struct{} 是“信号”通道:零字节的有效负载,只是
同步。
尝试一下
锻炼#go.m7.l2.e1
尝试:0加载中...
创建一个无缓冲的 int 通道 ch,从 goroutine 发送 42,在 main 中接收并打印它。
正在加载编辑器...
显示提示
如果没有缓冲区,发送方和接收方将同步。
3 次尝试后可用的解决方案
锻炼#go.m7.l2.e2
尝试:0加载中...
通过缓冲通道发送 1,2,3,关闭它,然后使用 for-range 打印所有内容。
正在加载编辑器...
显示提示
当通道关闭并排空时,通道上的“for range”结束。
3 次尝试后可用的解决方案
Quiz#go.m7.l2.e3
准备好当发送方发送但接收方尚未准备好时,UNBUFFERED 通道会做什么?
Go
ch := make(chan int)
ch <- 1 // ?回顾
- Channel = 类型化 FIFO 队列,在 goroutine 之间安全。
- 无缓冲:会合(发送方和接收方同步)。
- 缓冲:解耦,仅在满/空时阻塞。
close(ch):仅限发件人;for range消耗直到关闭。- 方向性:
chan<- T(仅发送)、<-chan T(仅接收)。 chan struct{}作为纯同步的信号通道。