章工运维 章工运维
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)

章工运维

业精于勤,荒于嬉
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)
  • python

  • shell

  • go

    • go基础

      • 指针
      • 数组
      • 切片
      • 字典
      • 结构体
      • 匿名组合
      • 方法
      • 接口
      • error接口
        • panic使用
      • Init函数和main函数
      • 下划线
      • go报错问题收集
      • Redis和MySQL结合的Web服务示例
      • go定义json数据
      • 使用go和vue编写学生管理系统
      • gin框架探索
    • 编程
    • go
    • go基础
    章工运维
    2024-11-21
    目录

    error接口

    # Go 的 error 接口介绍

    在 Go 语言中,error 是一个内置的接口,用于表示和处理错误。error 接口的定义非常简单:

    type error interface {
        Error() string
    }
    
    1
    2
    3

    只要一个类型实现了 Error() 方法,并返回一个字符串,就可以被视为实现了 error 接口。这种设计使得错误处理在 Go 中变得简洁和灵活。


    # 1. Go 的 error 接口基本用法

    # 1.1 创建和返回错误

    标准库提供了一个内置的函数 errors.New,用于创建一个简单的错误:

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func main() {
        err := errors.New("this is an error")
        fmt.Println(err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    输出:

    this is an error
    
    1

    # 1.2 使用 fmt.Errorf 创建格式化错误

    fmt.Errorf 可以创建带有格式化信息的错误:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        err := fmt.Errorf("file %s not found", "example.txt")
        fmt.Println(err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    输出:

    file example.txt not found
    
    1

    # 2. 自定义错误类型

    在实际开发中,我们通常需要自定义错误类型,以提供更多的错误上下文信息。

    # 2.1 定义自定义错误类型

    package main
    
    import (
        "fmt"
    )
    
    type MyError struct {
        Code    int
        Message string
    }
    
    func (e MyError) Error() string {
        return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
    }
    
    func main() {
        err := MyError{Code: 404, Message: "Resource not found"}
        fmt.Println(err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    输出:

    Error 404: Resource not found
    
    1

    # 3. 错误处理的基本模式

    Go 的错误处理主要依赖返回值,并通过检查错误值是否为 nil 来判断是否发生了错误。

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func divide(a, b int) (int, error) {
        if b == 0 {
            return 0, errors.New("division by zero")
        }
        return a / b, nil
    }
    
    func main() {
        result, err := divide(10, 0)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        fmt.Println("Result:", result)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    输出:

    Error: division by zero
    
    1

    # 4. 错误处理的最佳实践

    # 4.1 包装错误

    Go 提供了 errors.Unwrap、errors.Is 和 errors.As 等工具,用于解包和判断错误类型。

    package main
    
    import (
        "errors"
        "fmt"
    )
    
    func main() {
        baseErr := errors.New("base error")
        wrappedErr := fmt.Errorf("wrapped: %w", baseErr)
    
        fmt.Println(wrappedErr) // 输出: wrapped: base error
    
        // 检查是否是特定错误
        if errors.Is(wrappedErr, baseErr) {
            fmt.Println("wrappedErr contains baseErr")
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    输出:

    wrapped: base error
    wrappedErr contains baseErr
    
    1
    2

    # 4.2 类型断言和错误上下文处理

    通过类型断言处理自定义错误类型:

    package main
    
    import (
        "fmt"
    )
    
    type MyError struct {
        Code    int
        Message string
    }
    
    func (e MyError) Error() string {
        return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
    }
    
    func doSomething() error {
        return MyError{Code: 403, Message: "Forbidden"}
    }
    
    func main() {
        err := doSomething()
        if err != nil {
            // 检查是否是 MyError 类型
            if e, ok := err.(MyError); ok {
                fmt.Printf("Custom Error - Code: %d, Message: %s\n", e.Code, e.Message)
            } else {
                fmt.Println("Other Error:", err)
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    输出:

    Custom Error - Code: 403, Message: Forbidden
    
    1

    # 5. 实际应用案例

    # 5.1 文件读取错误处理

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func readFile(filename string) error {
        file, err := os.Open(filename)
        if err != nil {
            return fmt.Errorf("failed to open file %s: %w", filename, err)
        }
        defer file.Close()
        fmt.Println("File opened successfully")
        return nil
    }
    
    func main() {
        err := readFile("nonexistent.txt")
        if err != nil {
            fmt.Println("Error:", err)
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    输出:

    Error: failed to open file nonexistent.txt: open nonexistent.txt: no such file or directory
    
    1

    # 5.2 数据库操作错误处理

    package main
    
    import (
        "database/sql"
        "errors"
        "fmt"
        _ "github.com/mattn/go-sqlite3" // SQLite driver
    )
    
    func getUserByID(db *sql.DB, id int) (string, error) {
        var username string
        err := db.QueryRow("SELECT username FROM users WHERE id = ?", id).Scan(&username)
        if errors.Is(err, sql.ErrNoRows) {
            return "", fmt.Errorf("user with id %d not found: %w", id, err)
        }
        if err != nil {
            return "", fmt.Errorf("database error: %w", err)
        }
        return username, nil
    }
    
    func main() {
        db, err := sql.Open("sqlite3", ":memory:")
        if err != nil {
            fmt.Println("Error connecting to database:", err)
            return
        }
        defer db.Close()
    
        // Create a dummy table
        db.Exec("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)")
    
        username, err := getUserByID(db, 1)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        fmt.Println("Username:", username)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39

    输出:

    Error: user with id 1 not found: sql: no rows in result set
    
    1

    # 6. 总结

    • error 是 Go 内置的接口,通过 Error() 方法返回错误信息。
    • 使用 errors.New 和 fmt.Errorf 快速创建错误;也可以通过自定义类型实现复杂错误。
    • Go 提供了错误包装工具(%w)、解包(errors.Unwrap)、判断(errors.Is 和 errors.As)来处理复杂错误场景。
    • 错误处理贯穿 Go 编程的各个层面,是保证程序健壮性的关键。
    微信 支付宝
    上次更新: 2024/11/21, 10:50:23

    ← 接口 panic使用→

    最近更新
    01
    shell脚本模块集合
    05-13
    02
    生活小技巧(认知版)
    04-29
    03
    生活小技巧(防骗版)
    04-29
    更多文章>
    Theme by Vdoing | Copyright © 2019-2025 | 点击查看十年之约 | 鄂ICP备2024072800号
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式