Go之errors.New和fmt.Errorf 的区别小结

作者:

文章目录
  • 目录
    • error的基本用法
      • 1. 获取错误信息
      • 2. 在条件判断中使用
    • 基本区别
      • 1.函数签名
      • 2.使用场景
    • 详细对比
      • 1. 静态错误 vs 动态错误
      • 2. 错误比较
      • 3. 错误包装
    • 实际应用场景
      • 1. 使用 errors.New 的场景
      • 2. 使用 fmt.Errorf 的场景
    • 自定义错误类型
      • 1.基本用法
      • 2.自定义错误类型示例

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func main() {
        // 创建错误
        err := errors.New("文件不存在")
        
        // 获取错误信息
        errorMessage := err.Error()
        fmt.Println("错误信息:", errorMessage) // 输出: 错误信息: 文件不存在
        
        // 直接打印错误
        fmt.Println("直接打印:", err) // 输出: 直接打印: 文件不存在
    }
    

    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 {
            // 获取错误信息进行判断
            if err.Error() == "除数不能为零" {
                fmt.Println("检测到除零错误")
            }
            
            // 打印错误信息
            fmt.Println("错误:", err.Error())
            return
        }
        fmt.Println("结果:", result)
    }
    

    // errors.New - 只接受字符串
    func New(text string) error
    
    // fmt.Errorf - 接受格式化字符串和参数
    func Errorf(format string, a ...interface{}) error
    

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func main() {
        // errors.New - 简单静态错误
        err1 := errors.New("文件不存在")
        fmt.Println(err1)
        
        // fmt.Errorf - 动态格式化错误
        filename := "config.txt"
        err2 := fmt.Errorf("文件 %s 不存在", filename)
        fmt.Printf("err: %v n", err.Error())
    }
    

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    // 使用 errors.New - 适合静态错误
    var (
        ErrNotFound = errors.New("记录未找到")
        ErrInvalidInput = errors.New("无效输入")
        ErrTimeout = errors.New("操作超时")
    )
    
    // 使用 fmt.Errorf - 适合动态错误
    func validateAge(age int) error {
        if age < 0 {
            return fmt.Errorf("年龄不能为负数: %d", age)
        }
        if age > 150 {
            return fmt.Errorf("年龄不能超过150岁: %d", age)
        }
        return nil
    }
    
    func main() {
        // 静态错误
        fmt.Println(ErrNotFound)
        
        // 动态错误
        err := validateAge(-5)
        fmt.Println(err)
    }
    

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    var ErrNotFound = errors.New("记录未找到")
    
    func main() {
        // errors.New 创建的错误可以用于比较
        err1 := ErrNotFound
        err2 := ErrNotFound
        
        fmt.Println(err1 == err2) // true
        
        // fmt.Errorf 创建的错误每次都是新的
        err3 := fmt.Errorf("记录未找到")
        err4 := fmt.Errorf("记录未找到")
        
        fmt.Println(err3 == err4) // false
    }
    

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func processFile(filename string) error {
        // 模拟文件操作错误
        originalErr := errors.New("权限不足")
        
        // 使用 fmt.Errorf 包装错误
        return fmt.Errorf("处理文件 %s 失败: %v", filename, originalErr)
    }
    
    func main() {
        err := processFile("config.txt")
        fmt.Println(err) // 输出: 处理文件 config.txt 失败: 权限不足
    }
    

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    // 定义包级别的错误常量
    var (
        ErrUserNotFound = errors.New("用户不存在")
        ErrInvalidPassword = errors.New("密码错误")
        ErrDatabaseConnection = errors.New("数据库连接失败")
    )
    
    func authenticateUser(userID string, password string) error {
        if userID == "" {
            return ErrUserNotFound
        }
        
        if password == "" {
            return ErrInvalidPassword
        }
        
        // 验证逻辑...
        return nil
    }
    
    func main() {
        err := authenticateUser("", "123456")
        if err == ErrUserNotFound {
            fmt.Println("用户不存在")
        } else if err == ErrInvalidPassword {
            fmt.Println("密码错误")
        }
    }
    

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    func parseUserID(userIDStr string) (int, error) {
        userID, err := strconv.Atoi(userIDStr)
        if err != nil {
            return 0, fmt.Errorf("解析用户ID失败: %v", err)
        }
        
        if userID <= 0 {
            return 0, fmt.Errorf("用户ID必须大于0,当前值: %d", userID)
        }
        
        return userID, nil
    }
    
    func getUserInfo(userIDStr string) error {
        userID, err := parseUserID(userIDStr)
        if err != nil {
            return fmt.Errorf("获取用户信息失败: %v", err)
        }
        
        fmt.Printf("用户ID: %dn", userID)
        return nil
    }
    
    func main() {
        err := getUserInfo("abc")
        if err != nil {
            fmt.Println("错误:", err)
        }
    }
    

    package main
    
    import "fmt"
    
    // 自定义错误类型
    type ValidationError struct {
        Field   string
        Message string
    }
    
    // 实现 Error() 方法
    func (e *ValidationError) Error() string {
        return fmt.Sprintf("验证失败: 字段 '%s' - %s", e.Field, e.Message)
    }
    
    func validateUser(name string) error {
        if name == "" {
            return &ValidationError{
                Field:   "name",
                Message: "用户名不能为空",
            }
        }
        return nil
    }
    
    func main() {
        err := validateUser("")
        if err != nil {
            // 获取错误信息
            fmt.Println("错误信息:", err.Error())
            
            // 类型断言获取详细信息
            if validationErr, ok := err.(*ValidationError); ok {
                fmt.Printf("字段: %s, 消息: %sn", validationErr.Field, validationErr.Message)
            }
        }
    }
    

    package main
    
    import (
        "fmt"
        "time"
    )
    
    // 1. 基础自定义错误类型
    type ValidationError struct {
        Field   string
        Message string
        Value   interface{}
    }
    
    // 实现 error 接口
    func (e *ValidationError) Error() string {
        return fmt.Sprintf("验证失败: 字段 '%s' 的值 '%v' - %s", e.Field, e.Value, e.Message)
    }
    
    // 2. 业务错误类型
    type BusinessError struct {
        Code    int
        Message string
        Time    time.Time
    }
    
    func (e *BusinessError) Error() string {
        return fmt.Sprintf("[%d] %s (时间: %s)", e.Code, e.Message, e.Time.Format("2006-01-02 15:04:05"))
    }
    
    // 3. 网络错误类型
    type NetworkError struct {
        URL     string
        Status  int
        Message string
    }
    
    func (e *NetworkError) Error() string {
        return fmt.Sprintf("网络请求失败: %s (状态码: %d) - %s", e.URL, e.Status, e.Message)
    }
    
    // 4. 复合错误类型
    type CompositeError struct {
        Errors []error
        Context string
    }
    
    func (e *CompositeError) Error() string {
        if len(e.Errors) == 0 {
            return fmt.Sprintf("复合错误: %s", e.Context)
        }
        
        result := fmt.Sprintf("复合错误 [%s]:n", e.Context)
        for i, err := range e.Errors {
            result += fmt.Sprintf("  %d. %sn", i+1, err.Error())
        }
        return result
    }
    
    // 5. 带错误码的错误类型
    type CodedError struct {
        Code    int
        Message string
        Details map[string]interface{}
    }
    
    func (e *CodedError) Error() string {
        if len(e.Details) == 0 {
            return fmt.Sprintf("[%d] %s", e.Code, e.Message)
        }
        return fmt.Sprintf("[%d] %s - 详情: %v", e.Code, e.Message, e.Details)
    }
    
    // 使用示例函数
    func validateUser(name string, age int) error {
        if name == "" {
            return &ValidationError{
                Field:   "name",
                Message: "用户名不能为空",
                Value:   name,
            }
        }
        
        if age < 0 || age > 150 {
            return &ValidationError{
                Field:   "age",
                Message: "年龄必须在 0-150 之间",
                Value:   age,
            }
        }
        
        return nil
    }
    
    func processOrder(orderID string) error {
        if orderID == "" {
            return &BusinessError{
                Code:    1001,
                Message: "订单ID不能为空",
                Time:    time.Now(),
            }
        }
        
        // 模拟网络请求失败
        if orderID == "invalid" {
            return &NetworkError{
                URL:     "https://api.example.com/orders/" + orderID,
                Status:  404,
                Message: "订单不存在",
            }
        }
        
        return nil
    }
    
    func complexOperation() error {
        var errors []error
        
        // 模拟多个操作
        if err := validateUser("", 25); err != nil {
            errors = append(errors, err)
        }
        
        if err := processOrder(""); err != nil {
            errors = append(errors, err)
        }
        
        if len(errors) > 0 {
            return &CompositeError{
                Errors:  errors,
                Context: "用户注册操作",
            }
        }
        
        return nil
    }
    
    func main() {
        fmt.Println("=== 自定义错误类型示例 ===n")
        
        // 1. 验证错误示例
        fmt.Println("1. 验证错误:")
        if err := validateUser("", 25); err != nil {
            fmt.Printf("   %sn", err.Error())
        }
        
        if err := validateUser("张三", 200); err != nil {
            fmt.Printf("   %sn", err.Error())
        }
        
        // 2. 业务错误示例
        fmt.Println("n2. 业务错误:")
        if err := processOrder(""); err != nil {
            fmt.Printf("   %sn", err.Error())
        }
        
        // 3. 网络错误示例
        fmt.Println("n3. 网络错误:")
        if err := processOrder("invalid"); err != nil {
            fmt.Printf("   %sn", err.Error())
        }
        
        // 4. 复合错误示例
        fmt.Println("n4. 复合错误:")
        if err := complexOperation(); err != nil {
            fmt.Printf("   %sn", err.Error())
        }
        
        // 5. 带错误码的错误示例
        fmt.Println("n5. 带错误码的错误:")
        codedErr := &CodedError{
            Code:    5001,
            Message: "数据库连接失败",
            Details: map[string]interface{}{
                "host":     "localhost:3306",
                "database": "users",
                "reason":   "连接超时",
            },
        }
        fmt.Printf("   %sn", codedErr.Error())
        
        // 6. 错误类型检查示例
        fmt.Println("n6. 错误类型检查:")
        err := validateUser("", 25)
        if validationErr, ok := err.(*ValidationError); ok {
            fmt.Printf("   这是一个验证错误,字段: %sn", validationErr.Field)
        }
        
        if businessErr, ok := err.(*BusinessError); ok {
            fmt.Printf("   这是一个业务错误,错误码: %dn", businessErr.Code)
        }
    }
    

    到此这篇关于Go之errors.New 和 fmt.Errorf 的区别的文章就介绍到这了,更多相关Go errors.New 和 fmt.Errorf 内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • GO语言标准错误处理机制error用法实例
    • 解决启动MongoDB错误:error while loading shared libraries: libstdc++.so.6:cannot open shared object file:
    • 浅析golang开发Error的使用详解
    • Go 自定义error错误的处理方法
    • Go语言中实现打印堆栈的errors包的用法详解
    • golang常用库之pkg/errors包第三方错误处理包案例详解
    • Go error的使用方式详解

    站内搜索