指定通道的执行顺序

    说明这个主题的 Go 程序命名为 ,并分了五部分来介绍。

    defineOrder.go 的第一部分如下:

    A() 函数能被存储在 a 参数的通道中并阻塞。一旦在 main 函数中通道被解除阻塞,函数 A() 将开始工作。最后,它关闭 b 通道,解除在函数 B() 中的另个函数的阻塞。

    1. func B(a, b chan struct{}) {
    2. <-a
    3. fmt.Println("B()!")
    4. close(b)
    5. }

    B() 中的逻辑和函数 相同。这个函数被阻塞直到 a 通道关闭。然后它做自己的工作并关闭 b 通道。注意 ab 通道值这个函数的参数名。

    defineOrder.go 的第三段代码如下:

    C() 函数被阻塞并等待 a 通道关闭再开始工作。

    defineOrder.go 的第四部分如下:

    1. x := make(chan struct{})
    2. y := make(chan struct{})
    3. z := make(chan struct{})

    defineorder.go 的最后一段如下:

    执行 defineOrder.go 将产生期望的输出,即使 函数被调用了多次:

    1. $go run defineOrder.go
    2. B()!
    3. C()!
    4. C()!
    5. C()!
    6. C()!

    以 goroutines 调用 C() 函数多次会工作的很好,因为 C() 没有关闭任何通道。然而,如果您调用 A()B() 多次的话,您可能会得到如下错误信息: