为了账号安全,请及时绑定邮箱和手机立即绑定

为什么通道没有接收到成为结构体的成员

为什么通道没有接收到成为结构体的成员

Go
ibeautiful 2023-07-17 16:54:58
代码: 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条经验 获得超5个赞

你的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上尝试一下。



查看完整回答
反对 回复 2023-07-17
  • 1 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信