面试题答案
一键面试错误处理策略
- 独立处理每个通道:为每个数据来源通道单独创建一个goroutine来处理数据,这样一个通道出现错误不会影响其他通道。
- 错误隔离:在每个goroutine中捕获并处理本通道的错误,避免错误传播影响其他部分。
- 优雅退出:在出现错误时,确保该goroutine能优雅退出,同时不影响其他goroutine的运行。
代码示例
package main
import (
"fmt"
)
// 模拟数据来源通道
func dataSource1(c chan<- int, errCh chan<- error) {
defer close(c)
defer close(errCh)
for i := 0; i < 10; i++ {
if i == 5 {
errCh <- fmt.Errorf("data format error in dataSource1 at index %d", i)
return
}
c <- i
}
}
func dataSource2(c chan<- int, errCh chan<- error) {
defer close(c)
defer close(errCh)
for i := 10; i < 20; i++ {
c <- i
}
}
func processData(sourceName string, c <-chan int, errCh <-chan error) {
for {
select {
case data, ok := <-c:
if!ok {
return
}
fmt.Printf("%s received data: %d\n", sourceName, data)
case err, ok := <-errCh:
if!ok {
return
}
fmt.Printf("%s encountered error: %v\n", sourceName, err)
}
}
}
在main
函数中调用:
func main() {
ch1 := make(chan int)
errCh1 := make(chan error)
ch2 := make(chan int)
errCh2 := make(chan error)
go dataSource1(ch1, errCh1)
go dataSource2(ch2, errCh2)
go processData("DataSource1", ch1, errCh1)
go processData("DataSource2", ch2, errCh2)
// 防止主函数退出
select {}
}
优化思路
- 资源管理:在goroutine退出时,确保所有相关资源(如文件句柄、网络连接等)都被正确关闭和释放。
- 性能优化:如果数据量较大,可以考虑使用缓冲区(
make(chan int, bufferSize)
)来提高通道的读写性能。 - 错误记录与监控:将错误信息记录到日志文件中,方便后续排查问题;同时可以引入监控机制,实时了解程序的运行状态和错误情况。
- 错误恢复:对于一些可恢复的错误,可以在捕获错误后进行重试机制,尝试重新获取或处理数据。