代码: https: //play.golang.org/p/Oh3oTa7GIPXtype a struct { c chan bool}func (a *a) do() { a.c <- true}type b struct { c chan bool a a}func main() { b := b{ c: make(chan bool), a: a{c: make(chan bool)}, } go b.s() b.c <- true // below is to stay main gorutine alive done := make(chan bool) go func() { time.Sleep(10 * time.Second) done <- true }() for { select { case <-done: fmt.Println("Done!") return } }}func (b *b) s() { for { select { case <-b.c: fmt.Println("b c") b.a.do() case <-b.a.c: fmt.Println("b a c") } }}上述实际输出是b cDone!预期输出:b cb a cDone !我不明白为什么它不打印b a c?代码是不言自明的,如果还需要更多详细信息,请询问
1 回答
杨魅力
TA贡献1811条经验 获得超6个赞
你的maingoroutine 在 上发送一个值b.c,然后等待:
b.c <- true
从 main 启动的 goroutine:
go b.s()
这是从 接收的b.c,也是从 接收的b.a.c:
func (b *b) s() {
for {
select {
case <-b.c:
fmt.Println("b c")
b.a.do()
case <-b.a.c:
fmt.Println("b a c")
}
}
}
如果从 接收到一个值b.c,则该 goroutine 会尝试发送b.a.c(在a.do()方法中),并且您希望同一个goroutine 从 接收b.a.c。但由于b.a.c是无缓冲的,发送将被阻塞,因此它永远不会到达b.s()它可以/将从中接收的下一个迭代b.a.c。
如果一个通道是无缓冲的,那么只有当有另一个 goroutine 准备从它接收数据时,才可以在该通道上进行发送。
如果您对b.a.c通道进行缓冲,则可以在不阻塞的情况下继续发送,因此在下一次迭代中可以接收它:
a: a{c: make(chan bool, 1)}
通过此更改,您将获得预期的输出。在Go Playground上尝试一下。
- 1 回答
- 0 关注
- 101 浏览
添加回答
举报
0/150
提交
取消