MST

星途 面试题库

面试题:Go语言多返回值在并发编程中的应用

假设你正在使用Go语言进行并发编程,有一个场景:多个goroutine并发执行任务,每个任务会返回一个计算结果和可能的错误。你需要将这些结果收集起来,如果有任何一个任务出错,整个操作视为失败并返回错误。请设计并实现这样一个函数,展示如何有效利用Go语言的多返回值特性和并发原语来完成该任务。
17.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
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)
    }
}

代码解释

  1. concurrentTasks 函数
    • 接受一个函数切片 tasks,每个函数返回一个计算结果 int 和可能的错误 error
    • 使用 sync.WaitGroup 来等待所有的 goroutine 完成。
    • 使用 sync.Mutex 来保证对 results 切片和 hasErrorerr 变量的并发安全访问。
    • 遍历 tasks 切片,为每个任务启动一个 goroutine。在 goroutine 中,执行任务,若任务出错,设置 hasErrortrue 并记录错误。若任务成功,将结果添加到 results 切片中。
    • 等待所有 goroutine 完成后,根据 hasError 判断是否有任务出错,若有则返回 nil 和错误,否则返回结果切片和 nil 错误。
  2. main 函数
    • 定义了三个任务函数 task1task2task3,其中 task3 故意返回错误。
    • 将这些任务函数添加到 tasks 切片中,并调用 concurrentTasks 函数执行任务,根据返回的错误情况打印结果或错误信息。