go - 对“Go 中的并发”一书中描述的缓冲通道的不理解
问题描述
我阅读了 Katherine Cox-Buday 所写的“Go 中的并发”一书,但我不理解缓冲通道示例的评论。
作者说:
if a goroutine making writes to a channel has knowledge of how many writes it will make,
it can be useful to create a buffered channel whose capacity is the number of writes to be made
听起来很清楚,但例子令人困惑。
var stdoutBuff bytes.Buffer // <1>
defer stdoutBuff.WriteTo(os.Stdout) // <2>
intStream := make(chan int, 4) // <3>
go func() {
defer close(intStream)
defer fmt.Fprintln(&stdoutBuff, "Producer Done.")
for i := 0; i < 5; i++ {
fmt.Fprintf(&stdoutBuff, "Sending: %d\n", i)
intStream <- i
}
}()
for integer := range intStream {
fmt.Fprintf(&stdoutBuff, "Received %v.\n", integer)
}
带有注释的行<3>
有以下解释:
Here we create a buffered channel with a capacity of one.
有 4 个,而不是 1 个。是不是搞错了?
- 第二个例子——频道所有权,来源:https ://github.com/kat-co/concurrency-in-go-src/blob/master/gos-concurrency-building-blocks/channels/fig-chan-ownership.go
chanOwner := func() <-chan int {
resultStream := make(chan int, 5) // <1>
go func() { // <2>
defer close(resultStream) // <3>
for i := 0; i <= 5; i++ {
resultStream <- i
}
}()
return resultStream // <4>
}
标记为 的行<1>
有以下注释:
Since we know we will produce six results, we create a buffered channel of five
so that the goroutine can complete as quickly as possible.
我完全不明白这个评论。Goroutine 会被阻塞,因为通道有 5 条消息的容量,会产生 6 条消息,所以它会等到接收者收到第一条消息。
解决方案
因为我们知道我们将产生六个结果,所以我们创建了一个 5 个缓冲通道,以便 goroutine 可以尽快完成。
你是正确的,goroutine 将阻塞直到收到一个值。
创建一个容量比要发送的值数量少一的通道是没有意义的。如果通道容量等于或大于值的数量,则可以消除 goroutine:
chanOwner := func() <-chan int {
resultStream := make(chan int, 6)
for i := 0; i < cap(resultStream); i++ {
resultStream <- i
}
close(resultStream)
return resultStream
}()
或者通过消除匿名函数来实现:
chanOwner := make(chan int, 6)
for i := 0; i < cap(chanOwner); i++ {
resultStream <- i
}
close(chanOwner)
推荐阅读
- vba - 运行时错误“-2147352567(80020009)”:无法解析条件。"SQL="urn:schemas:httpmail:datereceived" 处出错..."
- c# - DataGrid 未填充
- angularjs - 当列具有布尔值和未定义值时,如何在 ng-grid 中自定义排序?
- android - 没有 AppCompat 的 TabLayout?
- java - Java Waffle - 绝对的初学者
- xml - 将子 XMLElement 添加到现有 XML
- mongodb - 使用 Mongoose 从 Array 中删除子文档
- jms - JMSTemplate 没有收到我之前发送的字符串?
- json - Alexa 添加到收藏夹
- wpf - WPF - 如何在子类控件(组合框)中获取模板化部分