设计思路
- 定义错误类型:为不同类型的错误定义独立的错误类型,方便区分。
- 封装数据与错误:发送到通道的数据结构不仅包含实际数据,还包含可能发生的错误。
- 接收与处理:接收方在处理数据时,检查错误并将其传递给主Goroutine。
- 主Goroutine处理:主Goroutine根据不同的错误类型进行相应处理,同时保证程序不会因错误而崩溃。
关键代码片段
package main
import (
"errors"
"fmt"
)
// 定义不同类型的错误
var (
ErrNetwork = errors.New("network error")
ErrParse = errors.New("data parse error")
)
// 定义数据与错误封装的结构体
type DataWithError struct {
Data interface{}
Error error
}
func main() {
dataCh := make(chan DataWithError)
// 模拟多个Goroutine发送数据
for i := 0; i < 3; i++ {
go func(id int) {
var dwErr DataWithError
// 模拟不同类型错误
if id == 1 {
dwErr = DataWithError{Data: "data1", Error: ErrNetwork}
} else if id == 2 {
dwErr = DataWithError{Data: "data2", Error: ErrParse}
} else {
dwErr = DataWithError{Data: "data3", Error: nil}
}
dataCh <- dwErr
}(i)
}
// 接收并处理数据和错误
go func() {
for dwErr := range dataCh {
if dwErr.Error != nil {
switch dwErr.Error {
case ErrNetwork:
fmt.Printf("Network error occurred while processing data: %v\n", dwErr.Data)
case ErrParse:
fmt.Printf("Parse error occurred while processing data: %v\n", dwErr.Data)
default:
fmt.Printf("Unknown error occurred: %v\n", dwErr.Error)
}
} else {
fmt.Printf("Processed data successfully: %v\n", dwErr.Data)
}
}
}()
// 防止主Goroutine退出
select {}
}