- 使用
sync.WaitGroup
和chan
收集结果和处理错误:
sync.WaitGroup
用于等待所有goroutine
完成。
- 使用带缓冲的通道(
chan
)来收集每个goroutine
的结果和错误。
- 示例代码如下:
package main
import (
"fmt"
"sync"
)
// 定义一个函数,模拟任务,返回多个结果和可能的错误
func task(id int) (int, string, error) {
if id == 2 {
return 0, "", fmt.Errorf("task %d failed", id)
}
return id * 10, fmt.Sprintf("result from task %d", id), nil
}
func main() {
var wg sync.WaitGroup
resultChan := make(chan struct {
id int
num int
str string
error error
}, 10)
// 启动多个goroutine
for i := 1; i <= 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
num, str, err := task(id)
resultChan <- struct {
id int
num int
str string
error error
}{id, num, str, err}
}(i)
}
go func() {
wg.Wait()
close(resultChan)
}()
// 处理结果和错误
for res := range resultChan {
if res.error != nil {
fmt.Printf("Task %d error: %v\n", res.id, res.error)
} else {
fmt.Printf("Task %d result: num=%d, str=%s\n", res.id, res.num, res.str)
}
}
}
- 并发安全阐述:
- 通道(
chan
)的并发安全:在Go语言中,通道本身是线程安全的。多个goroutine
可以安全地向通道发送数据和从通道接收数据,不需要额外的锁机制。在上述代码中,多个goroutine
向resultChan
发送结果和错误,不会出现数据竞争问题。
sync.WaitGroup
的使用:sync.WaitGroup
用于同步goroutine
,确保所有goroutine
完成任务后再关闭通道。wg.Add(1)
用于增加等待组的计数,wg.Done()
用于减少计数,wg.Wait()
用于阻塞当前goroutine
,直到所有goroutine
调用wg.Done()
,这样保证了在关闭通道前所有goroutine
都有机会将结果发送到通道中,避免了提前关闭通道导致数据丢失的问题。