1.12 错误处理
error 接口
go
package main
import (
"errors"
"fmt"
)
// 创建错误
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
func main() {
// 错误检查
result, err := divide(10, 0)
if err != nil {
fmt.Println("错误:", err)
return
}
// 错误处理模式
// 1. 直接返回
if err != nil {
return err
}
// 2. 包装错误
if err != nil {
return fmt.Errorf("处理失败:%w", err)
}
// 3. 记录日志
if err != nil {
logError(err)
}
// 4. 忽略错误
result, _ = divide(10, 2)
}
func logError(err error) {
fmt.Println("记录错误:", err)
}自定义错误类型
go
package main
import (
"errors"
"fmt"
"time"
)
// 自定义错误
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("验证错误 [%s]: %s", e.Field, e.Message)
}
// 带堆栈的错误
type AppError struct {
Code string
Message string
Err error
Time time.Time
}
func (e *AppError) Error() string {
return fmt.Sprintf("[%s] %s: %v", e.Code, e.Message, e.Err)
}
func (e *AppError) Unwrap() error {
return e.Err
}
// 错误类型判断
func validateAge(age int) error {
if age < 0 {
return &ValidationError{Field: "age", Message: "年龄不能为负"}
}
return nil
}
func main() {
err := validateAge(-1)
if err != nil {
if ve, ok := err.(*ValidationError); ok {
fmt.Printf("字段:%s, 消息:%s\n", ve.Field, ve.Message)
}
}
// 哨兵错误
var ErrNotFound = errors.New("未找到")
}errors 包
go
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("记录未找到")
func findUser(id int) error {
if id < 0 {
return ErrNotFound
}
return nil
}
func main() {
// errors.Is - 检查错误链
err := findUser(-1)
if errors.Is(err, ErrNotFound) {
fmt.Println("输入无效")
}
// errors.As - 提取特定类型错误
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Println("字段:", ve.Field)
}
// errors.Join - 合并错误 (Go 1.20+)
err1 := errors.New("错误 1")
err2 := errors.New("错误 2")
err3 := errors.Join(err1, err2)
fmt.Println(err3)
// 错误包装
baseErr := errors.New("原始错误")
wrappedErr := fmt.Errorf("包装:%w", baseErr)
fmt.Println(errors.Unwrap(wrappedErr))
}panic 与 recover
go
package main
import "fmt"
func main() {
// 安全除法
result := safeDivide(10, 0)
fmt.Println("结果:", result)
// recover 示例
safeFunc()
}
func safeDivide(a, b int) (result int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("捕获 panic:", r)
result = 0
}
}()
if b == 0 {
panic("除数为零")
}
return a / b
}
func safeFunc() {
defer func() {
if r := recover(); r != nil {
fmt.Println("从 panic 恢复:", r)
}
}()
panic("测试 panic")
}