Files
tyapi-server/internal/infrastructure/external/README.md
2025-08-27 22:19:19 +08:00

124 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 外部服务错误处理修复说明
## 问题描述
在外部服务WestDex、Yushan、Zhicha使用 `fmt.Errorf("%w: %s", ErrXXX, err)` 包装错误后,外层的 `errors.Is(err, ErrXXX)` 无法正确识别错误类型。
## 问题原因
`fmt.Errorf` 创建的包装错误虽然实现了 `Unwrap()` 接口,但没有实现 `Is()` 接口,因此 `errors.Is` 无法正确判断错误类型。
## 修复方案
统一使用 `errors.Join` 来组合错误,这是 Go 1.20+ 的标准做法,天然支持 `errors.Is` 判断。
## 修复内容
### 1. WestDex 服务 (`westdex_service.go`)
#### 修复前:
```go
// 无法被 errors.Is 识别的错误包装
err = fmt.Errorf("%w: %s", ErrSystem, marshalErr.Error())
err = fmt.Errorf("%w: %s", ErrDatasource, westDexResp.Message)
```
#### 修复后:
```go
// 可以被 errors.Is 正确识别的错误组合
err = errors.Join(ErrSystem, marshalErr)
err = errors.Join(ErrDatasource, fmt.Errorf(westDexResp.Message))
```
### 2. Yushan 服务 (`yushan_service.go`)
#### 修复前:
```go
// 无法被 errors.Is 识别的错误包装
err = fmt.Errorf("%w: %s", ErrSystem, err.Error())
err = fmt.Errorf("%w: %s", ErrDatasource, "羽山请求retdata为空")
```
#### 修复后:
```go
// 可以被 errors.Is 正确识别的错误组合
err = errors.Join(ErrSystem, err)
err = errors.Join(ErrDatasource, fmt.Errorf("羽山请求retdata为空"))
```
### 3. Zhicha 服务 (`zhicha_service.go`)
#### 修复前:
```go
// 无法被 errors.Is 识别的错误包装
err = fmt.Errorf("%w: %s", ErrSystem, marshalErr.Error())
err = fmt.Errorf("%w: %s", ErrDatasource, "HTTP状态码 %d", response.StatusCode)
```
#### 修复后:
```go
// 可以被 errors.Is 正确识别的错误组合
err = errors.Join(ErrSystem, marshalErr)
err = errors.Join(ErrDatasource, fmt.Errorf("HTTP状态码 %d", response.StatusCode))
```
## 修复效果
### 修复前的问题:
```go
// 在应用服务层
if errors.Is(err, westdex.ErrDatasource) {
// 这里无法正确识别,因为 fmt.Errorf 包装的错误
// 没有实现 Is() 接口
return ErrDatasource
}
```
### 修复后的效果:
```go
// 在应用服务层
if errors.Is(err, westdex.ErrDatasource) {
// 现在可以正确识别了!
return ErrDatasource
}
if errors.Is(err, westdex.ErrSystem) {
// 系统错误也能正确识别
return ErrSystem
}
```
## 优势
1. **完全兼容**`errors.Is` 现在可以正确识别所有错误类型
2. **标准做法**:使用 Go 1.20+ 的 `errors.Join` 标准库功能
3. **性能优秀**:标准库实现,性能优于自定义解决方案
4. **维护简单**:无需自定义错误类型,代码更简洁
## 注意事项
1. **Go版本要求**:需要 Go 1.20 或更高版本(项目使用 Go 1.23.4,完全满足)
2. **错误消息格式**`errors.Join` 使用换行符分隔多个错误
3. **向后兼容**:现有的错误处理代码无需修改
## 测试验证
所有修复后的外部服务都能正确编译:
```bash
go build ./internal/infrastructure/external/westdex/...
go build ./internal/infrastructure/external/yushan/...
go build ./internal/infrastructure/external/zhicha/...
```
## 总结
通过统一使用 `errors.Join` 修复外部服务的错误处理,现在:
-`errors.Is(err, ErrDatasource)` 可以正确识别数据源异常
-`errors.Is(err, ErrSystem)` 可以正确识别系统异常
-`errors.Is(err, ErrNotFound)` 可以正确识别查询为空
- ✅ 错误处理逻辑更加清晰和可靠
- ✅ 符合 Go 1.20+ 的最佳实践
这个修复确保了整个系统的错误处理链路都能正确工作,提高了系统的可靠性和可维护性。