Go主协程如何等其余协程完再操作

东白随记
0 评论
/ /
0 阅读
/
1965 字
17 2024-09

在Go语言中,如果你希望主协程等待其他协程完成某些操作后再继续执行,你可以使用`sync.WaitGroup`或者`channel`(通道)来实现。

### 使用`sync.WaitGroup`

`sync.WaitGroup`是Go语言标准库中提供的一个工具,用于等待一组协程完成。你可以为每个启动的协程调用`Add`方法增加计数器,然后在所有协程执行完毕后调用`Wait`方法来阻塞主协程直到所有协程完成。

```go

package main

import (

"fmt"

"sync"

"time"

)

func doWork(wg *sync.WaitGroup, id int) {

defer wg.Done() // 在函数结束时调用 Done 来通知 WaitGroup 任务已完成

// 模拟一些工作

fmt.Printf("协程 %d 开始工作...\n", id)

time.Sleep(time.Second) // 模拟耗时操作

fmt.Printf("协程 %d 工作完成.\n", id)

}

func main() {

var wg sync.WaitGroup

// 启动多个协程

for i := 1; i <= 5; i++ {

wg.Add(1) // 为每个将要执行的协程增加计数器

go doWork(&wg, i) // 启动协程并传递WaitGroup的指针给它

}

// 主协程等待所有其他协程完成工作后继续执行

wg.Wait() // 阻塞主协程直到所有子协程的 Done 被调用,即所有子协程执行完毕

fmt.Println("所有其他协程已经完成,主协程继续...")

}

```

### 使用Channel(通道)

另一个常见的方法是使用通道(channel)来等待多个协程的完成。你可以为每个需要等待的任务发送一个信号到通道中,并在主协程中通过接收该信号来等待所有任务完成。

```go

package main

import (

"fmt"

"time"

)

func doWork(ch chan bool) {

// 模拟一些工作...

fmt.Printf("协程开始工作...\n")

time.Sleep(time.Second) // 模拟耗时操作

ch <- true // 完成工作后发送信号到通道中表示任务已完成

}

func main() {

ch := make(chan bool, 5) // 创建一个带有缓冲的通道来存放信号(实际中通道类型应与工作结果类型匹配)

// 启动多个协程并将它们的工作结果发送到通道中

for i := 1; i <= 5; i++ {

go doWork(ch) // 启动一个协程执行任务并将结果发送到通道中

}

// 主协程等待所有信号被接收(即所有任务完成)再继续执行后续操作...

for i := 0; i < 5; i++ { <-ch } // 从通道中接收信号直到所有信号都被接收(即所有任务都已完成)

fmt.Println("所有其他协程已经完成,主协程继续...") // 所有任务完成后,主协程继续执行后续操作...

}

```

在这两个例子中,你可以看到如何等待一组协程完成特定的任务后再进行后续的操作。在大多数情况下,你应该根据实际情况选择合适的方法。对于简单的同步任务,`sync.WaitGroup`通常是更加简单直接的选择;而如果涉及到更复杂的通信模式或需要传递数据时,通道(channel)则更为合适。