有关golang频道的一些问题

时间:2019-10-04 15:58:07

标签: go channel goroutine

我正在YouTube上观看有关并发模式的视频。 有一个乒乓球示例:

type Ball struct{ hits int }
func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)

    table <- new(Ball)
    time.Sleep(1 * time.Second)
    <-table
}

func player(name string, table chan *Ball) {
    for {
        ball := <-table
        ball.hits++
        fmt.Println(name, ball.hits)
        time.Sleep(100 * time.Millisecond)
        table <- ball
    }
}

哪个应该给出结果:

Ping 1
Pong 2
Ping 3
Pong 4
...

但是,如果我删除一个球员的例行程序,例如“ pong”:

// go player("pong", table) // remove this line

我只有一个结果:

Ping 1

我不知道func播放器中有一个for循环,并且'table'频道将Ball传给ball,在循环结束时,我们将Ball放回了频道表。为什么玩家“ ping”不能自己玩?

1 个答案:

答案 0 :(得分:5)

该通道是无缓冲的,这意味着一个例程必须接收才能完成另一个例程的发送。如果您删除pong播放器,则会阻止ping播放器在频道上发送(pong不能接收),因此它将永远不会移至循环的下一个迭代收到自己的消息。

如果要缓冲通道,则在缓冲区table := make(chan *Ball, 1)中如果有空间,则发送将是非阻塞的。这样一来,一个球就可以“保留”在通道的缓冲区中,直到接收器准备就绪为止。