go channel 应由能确定所有发送都已完成的一方关闭。只有一个生产者时由它关闭。多个生产者共享一个 channel 时,由协调协程等待全部生产者结束后关闭。
单个生产者发完再关闭
把示例保存为 main.go。消费者用 range 持续读取,直到 Channel 关闭且缓冲数据读完。
package main
import "fmt"
func main() {
jobs := make(chan int)
go func() {
defer close(jobs)
for _, value := range []int{1, 2, 3} {
jobs <- value
}
}()
for value := range jobs {
fmt.Println(value)
}
}
运行 go run main.go,预期输出 1、2、3,然后程序退出。
多个生产者由协调协程统一关闭
在另一个目录把下面的完整程序保存为 main.go。先登记生产者数量,再启动协程。
package main
import (
"fmt"
"sync"
)
func main() {
jobs := make(chan int)
var producers sync.WaitGroup
producers.Add(2)
for _, value := range []int{10, 20} {
go func(value int) {
defer producers.Done()
jobs <- value
}(value)
}
go func() {
producers.Wait()
close(jobs)
}()
total := 0
for value := range jobs {
total += value
}
fmt.Println(total)
}两项到达的顺序可能变化,合计应始终是 30。
用竞态检测运行示例
在支持 Go 竞态检测的本机环境运行。
go run -race main.go
如果消费者可能提前结束,应加入取消信号,让生产者也能停止等待发送。


















