指定通道的执行顺序
说明这个主题的 Go 程序命名为 ,并分了五部分来介绍。
defineOrder.go
的第一部分如下:
A()
函数能被存储在 a
参数的通道中并阻塞。一旦在 main
函数中通道被解除阻塞,函数 A()
将开始工作。最后,它关闭 b
通道,解除在函数 B()
中的另个函数的阻塞。
func B(a, b chan struct{}) {
<-a
fmt.Println("B()!")
close(b)
}
B()
中的逻辑和函数 相同。这个函数被阻塞直到 a
通道关闭。然后它做自己的工作并关闭 b
通道。注意 a
和 b
通道值这个函数的参数名。
defineOrder.go
的第三段代码如下:
C()
函数被阻塞并等待 a
通道关闭再开始工作。
defineOrder.go
的第四部分如下:
x := make(chan struct{})
y := make(chan struct{})
z := make(chan struct{})
defineorder.go
的最后一段如下:
执行 defineOrder.go
将产生期望的输出,即使 函数被调用了多次:
$go run defineOrder.go
B()!
C()!
C()!
C()!
C()!
以 goroutines 调用 C()
函数多次会工作的很好,因为 C()
没有关闭任何通道。然而,如果您调用 A()
或 B()
多次的话,您可能会得到如下错误信息: