MST

星途 面试题库

面试题:Go语言中Goroutine常见错误处理方式

在Go语言中,当一个Goroutine发生错误时,通常有哪些方式来处理这个错误?请举例说明如何在主Goroutine中捕获并处理子Goroutine中的错误。
27.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

在Go语言中,处理Goroutine错误常见方式如下:

  1. 通过返回值处理错误:在函数内部进行错误检查和处理,并将错误作为返回值返回。
    package main
    
    import (
        "fmt"
    )
    
    func divide(a, b int) (int, error) {
        if b == 0 {
            return 0, fmt.Errorf("division by zero")
        }
        return a / b, nil
    }
    
  2. 使用sync.WaitGroup和通道处理子Goroutine错误
    package main
    
    import (
        "fmt"
        "sync"
    )
    
    func worker(wg *sync.WaitGroup, errChan chan error) {
        defer wg.Done()
        // 模拟可能出错的操作
        if someCondition {
            errChan <- fmt.Errorf("worker error")
            return
        }
        errChan <- nil
    }
    
    func main() {
        var wg sync.WaitGroup
        errChan := make(chan error)
        wg.Add(1)
        go worker(&wg, errChan)
    
        go func() {
            wg.Wait()
            close(errChan)
        }()
    
        for err := range errChan {
            if err != nil {
                fmt.Printf("Caught error: %v\n", err)
            }
        }
    }
    
  3. 使用context.Context处理错误:可以在context中传递取消信号或携带错误信息。
    package main
    
    import (
        "context"
        "fmt"
    )
    
    func worker(ctx context.Context) error {
        select {
        case <-ctx.Done():
            return ctx.Err()
        default:
            // 模拟正常工作
            return nil
        }
    }
    
    func main() {
        ctx, cancel := context.WithCancel(context.Background())
        go func() {
            err := worker(ctx)
            if err != nil {
                fmt.Printf("Caught error: %v\n", err)
            }
        }()
        // 模拟一段时间后取消
        cancel()
    }
    

在主Goroutine中捕获并处理子Goroutine中的错误,通常采用上述第二点的方式,通过通道将子Goroutine的错误传递出来,主Goroutine从通道中接收错误并处理。如代码示例:

package main

import (
    "fmt"
    "sync"
)

func subGoroutine(wg *sync.WaitGroup, errChan chan error) {
    defer wg.Done()
    // 模拟子Goroutine出错
    err := someFunctionThatMightFail()
    if err != nil {
        errChan <- err
        return
    }
    errChan <- nil
}

func someFunctionThatMightFail() error {
    // 实际逻辑,这里简单返回一个错误示例
    return fmt.Errorf("simulated error")
}

func main() {
    var wg sync.WaitGroup
    errChan := make(chan error)
    wg.Add(1)
    go subGoroutine(&wg, errChan)

    go func() {
        wg.Wait()
        close(errChan)
    }()

    for err := range errChan {
        if err != nil {
            fmt.Printf("Main Goroutine caught error: %v\n", err)
        }
    }
}