面试题答案
一键面试package main
import (
"fmt"
"sync"
)
// ErrorCollector 用于收集并发错误
type ErrorCollector struct {
mu sync.Mutex
errors []error
}
// AddError 添加错误到收集器
func (ec *ErrorCollector) AddError(err error) {
ec.mu.Lock()
ec.errors = append(ec.errors, err)
ec.mu.Unlock()
}
// GetErrors 获取所有收集到的错误
func (ec *ErrorCollector) GetErrors() []error {
ec.mu.Lock()
defer ec.mu.Unlock()
return ec.errors
}
func main() {
var wg sync.WaitGroup
errorCollector := ErrorCollector{}
// 模拟多个goroutine执行任务
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// 模拟可能出现错误的任务
if id == 1 {
errorCollector.AddError(fmt.Errorf("goroutine %d has an error", id))
}
}(i)
}
wg.Wait()
// 处理收集到的错误
errors := errorCollector.GetErrors()
if len(errors) > 0 {
fmt.Println("Encountered errors:")
for _, err := range errors {
fmt.Println(err)
}
} else {
fmt.Println("No errors occurred")
}
}
关键设计点解释
-
ErrorCollector结构体:
- 使用
sync.Mutex
来确保在多个goroutine并发添加错误时数据的一致性。 errors
切片用于存储收集到的所有错误。
- 使用
-
AddError方法:
- 该方法负责将错误添加到
errors
切片中。 - 通过加锁和解锁操作,保证在并发环境下添加错误的线程安全性。
- 该方法负责将错误添加到
-
GetErrors方法:
- 用于获取所有收集到的错误。
- 同样通过加锁和解锁操作,保证在读取错误列表时的线程安全性。
-
主函数中的并发操作:
- 使用
sync.WaitGroup
来等待所有goroutine完成任务。 - 每个goroutine模拟执行可能出错的任务,一旦出错,调用
AddError
方法将错误添加到收集器中。 - 最后,通过
GetErrors
方法获取所有错误并进行统一处理。这样可以确保在出现错误时整个程序能够做出正确的响应,同时利用Go语言的并发特性保证程序的性能和资源利用效率。
- 使用