插件窝 干货文章 Go语言中如何用单个Channel精确控制多个Goroutine的执行顺序?

Go语言中如何用单个Channel精确控制多个Goroutine的执行顺序?

Goroutine 信号 一个 worker 676    来源:    2025-03-11

在Go语言中,可以使用单个Channel来精确控制多个Goroutine的执行顺序。具体来说,可以通过在Goroutine之间传递信号(如struct{}类型的空结构体)来协调它们的执行顺序。以下是一个示例,展示了如何使用单个Channel来控制三个Goroutine的执行顺序:

package main

import (
    "fmt"
    "time"
)

func worker(id int, ch chan struct{}, nextCh chan struct{}) {
    <-ch // 等待信号
    fmt.Printf("Worker %d is running\n", id)
    time.Sleep(500 * time.Millisecond) // 模拟工作
    nextCh <- struct{}{} // 发送信号给下一个Goroutine
}

func main() {
    // 创建一个Channel用于控制Goroutine的执行顺序
    ch := make(chan struct{})
    nextCh1 := make(chan struct{})
    nextCh2 := make(chan struct{})

    // 启动三个Goroutine
    go worker(1, ch, nextCh1)
    go worker(2, nextCh1, nextCh2)
    go worker(3, nextCh2, ch)

    // 发送初始信号,启动第一个Goroutine
    ch <- struct{}{}

    // 等待最后一个Goroutine完成
    <-ch

    fmt.Println("All workers have completed.")
}

代码解释:

  1. Channel定义

    • ch:用于控制第一个Goroutine的启动。
    • nextCh1nextCh2:用于在Goroutine之间传递信号。
  2. Goroutine定义

    • 每个worker函数接收两个Channel:一个用于接收信号(ch),另一个用于发送信号给下一个Goroutine(nextCh)。
    • 当Goroutine接收到信号后,它会执行一些工作(这里用time.Sleep模拟),然后发送信号给下一个Goroutine。
  3. 启动Goroutine

    • 三个Goroutine分别启动,等待各自的信号。
  4. 发送初始信号

    • 主Goroutine通过ch <- struct{}{}发送初始信号,启动第一个Goroutine。
  5. 等待最后一个Goroutine完成

    • 主Goroutine通过<-ch等待最后一个Goroutine完成。

输出结果:

Worker 1 is running
Worker 2 is running
Worker 3 is running
All workers have completed.

总结:

通过这种方式,你可以使用单个Channel来精确控制多个Goroutine的执行顺序。每个Goroutine在完成自己的工作后,会通过Channel通知下一个Goroutine开始执行。这种方法可以确保Goroutine按照预期的顺序执行。