writing/reading 多值 to/from 无缓冲通道在 Go 中如何工作?
How does writing/reading multiple values to/from a unbuffered channel work in Go?
这似乎挑战了我对无缓冲通道的理解,即它只能取一个值,然后它会阻塞 reader 来读取它。
- 下面的代码
writeToChan
如何写出3个值?
- 更令人惊讶的是,这些值是如何在以后读取的,尽管顺序不同?
摘自https://golang.org/doc/effective_go#channels
Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go writeToChan(ch)
go rdFrmChan(ch)
x := <- ch
fmt.Println("main read 1 -:",x)
fmt.Println("main read 2 -:",<-ch)
}
func writeToChan(c chan int) {
time.Sleep(time.Second * 1)
c <- 42
c <- 27
c <- 9
}
func rdFrmChan(c chan int) {
fmt.Println("Go routine read :", <-c)
}
输出:
Go routine read : 27
主读 1 -: 42
主读 2 -: 9
Playground link: https://play.golang.org/p/DYzfYh-kXnC
粘贴的每一行摘录都由您的示例代码证明,如果您了解事件发生的顺序。
goroutines 启动后,您的主例程被阻止从通道 c
读取,因为它还没有看到要读取的值。 writeToChan
例程在将第一个值写入通道之前等待一秒钟
goroutine rdFrmChan
也被阻塞了,因为它在通道 ch
上等待读取
1s后,当writeToChan
上的sleep到期,第一个write(c <- 42
)会先unblock你的main routine,导致value存入x
即 42
接下来 rdFrmChan
在下一次写入通道 (c <- 27
) 时解除阻塞并看到值 27。例程在打印值 [ 后于此时终止=21=]
此时,只有写入值和读取值。 goroutine 的第三次写入 (c <- 9
) 允许主例程读取值作为 <-ch
的一部分并打印它
这似乎挑战了我对无缓冲通道的理解,即它只能取一个值,然后它会阻塞 reader 来读取它。
- 下面的代码
writeToChan
如何写出3个值? - 更令人惊讶的是,这些值是如何在以后读取的,尽管顺序不同?
摘自https://golang.org/doc/effective_go#channels
Receivers always block until there is data to receive. If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go writeToChan(ch)
go rdFrmChan(ch)
x := <- ch
fmt.Println("main read 1 -:",x)
fmt.Println("main read 2 -:",<-ch)
}
func writeToChan(c chan int) {
time.Sleep(time.Second * 1)
c <- 42
c <- 27
c <- 9
}
func rdFrmChan(c chan int) {
fmt.Println("Go routine read :", <-c)
}
输出:
Go routine read : 27
主读 1 -: 42
主读 2 -: 9
Playground link: https://play.golang.org/p/DYzfYh-kXnC
粘贴的每一行摘录都由您的示例代码证明,如果您了解事件发生的顺序。
goroutines 启动后,您的主例程被阻止从通道
c
读取,因为它还没有看到要读取的值。writeToChan
例程在将第一个值写入通道之前等待一秒钟goroutine
上等待读取rdFrmChan
也被阻塞了,因为它在通道ch
1s后,当
writeToChan
上的sleep到期,第一个write(c <- 42
)会先unblock你的main routine,导致value存入x
即 42接下来
rdFrmChan
在下一次写入通道 (c <- 27
) 时解除阻塞并看到值 27。例程在打印值 [ 后于此时终止=21=]此时,只有写入值和读取值。 goroutine 的第三次写入 (
c <- 9
) 允许主例程读取值作为<-ch
的一部分并打印它