面试题答案
一键面试package main
import (
"fmt"
"sync"
)
func concurrentTasks(tasks []func() (int, error)) (results []int, err error) {
var wg sync.WaitGroup
var mu sync.Mutex
var hasError bool
for _, task := range tasks {
wg.Add(1)
go func(t func() (int, error)) {
defer wg.Done()
result, e := t()
if e != nil {
mu.Lock()
hasError = true
err = e
mu.Unlock()
return
}
mu.Lock()
results = append(results, result)
mu.Unlock()
}(task)
}
wg.Wait()
if hasError {
return nil, err
}
return results, nil
}
你可以使用如下方式调用这个函数:
func main() {
task1 := func() (int, error) {
return 1, nil
}
task2 := func() (int, error) {
return 2, nil
}
task3 := func() (int, error) {
return 0, fmt.Errorf("task3 error")
}
tasks := []func() (int, error){task1, task2, task3}
results, err := concurrentTasks(tasks)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Results:", results)
}
}
代码解释
concurrentTasks
函数:- 接受一个函数切片
tasks
,每个函数返回一个计算结果int
和可能的错误error
。 - 使用
sync.WaitGroup
来等待所有的 goroutine 完成。 - 使用
sync.Mutex
来保证对results
切片和hasError
、err
变量的并发安全访问。 - 遍历
tasks
切片,为每个任务启动一个 goroutine。在 goroutine 中,执行任务,若任务出错,设置hasError
为true
并记录错误。若任务成功,将结果添加到results
切片中。 - 等待所有 goroutine 完成后,根据
hasError
判断是否有任务出错,若有则返回nil
和错误,否则返回结果切片和nil
错误。
- 接受一个函数切片
main
函数:- 定义了三个任务函数
task1
、task2
和task3
,其中task3
故意返回错误。 - 将这些任务函数添加到
tasks
切片中,并调用concurrentTasks
函数执行任务,根据返回的错误情况打印结果或错误信息。
- 定义了三个任务函数