错误基础 #

一、error接口 #

1.1 接口定义 #

go
type error interface {
    Error() string
}

1.2 创建错误 #

go
import "errors"

err := errors.New("something went wrong")

1.3 fmt.Errorf #

go
err := fmt.Errorf("failed to open file: %s", filename)

二、错误检查 #

2.1 基本检查 #

go
result, err := someFunction()
if err != nil {
    return err
}

2.2 nil检查 #

go
if err != nil {
    fmt.Println("Error:", err)
}

2.3 错误处理模式 #

go
func doSomething() error {
    if err := step1(); err != nil {
        return err
    }
    
    if err := step2(); err != nil {
        return err
    }
    
    return nil
}

三、错误传播 #

3.1 返回错误 #

go
func readFile(path string) ([]byte, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, err
    }
    return data, nil
}

3.2 添加上下文 #

go
func processFile(path string) error {
    data, err := os.ReadFile(path)
    if err != nil {
        return fmt.Errorf("failed to read %s: %w", path, err)
    }
    return nil
}

四、实际应用 #

4.1 文件操作 #

go
func openFile(path string) (*os.File, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, fmt.Errorf("open file: %w", err)
    }
    return f, nil
}

4.2 HTTP请求 #

go
func fetch(url string) ([]byte, error) {
    resp, err := http.Get(url)
    if err != nil {
        return nil, fmt.Errorf("fetch %s: %w", url, err)
    }
    defer resp.Body.Close()
    
    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("status %d", resp.StatusCode)
    }
    
    return io.ReadAll(resp.Body)
}

4.3 数据库操作 #

go
func queryUser(db *sql.DB, id int) (*User, error) {
    row := db.QueryRow("SELECT id, name FROM users WHERE id = ?", id)
    
    var user User
    err := row.Scan(&user.ID, &user.Name)
    if err != nil {
        if err == sql.ErrNoRows {
            return nil, fmt.Errorf("user %d not found", id)
        }
        return nil, fmt.Errorf("query user: %w", err)
    }
    
    return &user, nil
}

五、最佳实践 #

5.1 早返回 #

go
func process(data []byte) error {
    if len(data) == 0 {
        return errors.New("empty data")
    }
    
    // 处理...
    return nil
}

5.2 添加上下文 #

go
if err != nil {
    return fmt.Errorf("operation failed: %w", err)
}

5.3 不要忽略错误 #

go
// 不好
data, _ := os.ReadFile(path)

// 好
data, err := os.ReadFile(path)
if err != nil {
    return err
}

六、总结 #

错误处理要点:

方法 说明
errors.New 创建简单错误
fmt.Errorf 格式化错误
%w 包装错误

关键点:

  1. error接口:Error() string方法
  2. 错误检查:if err != nil
  3. 错误传播:返回错误给调用者
  4. 添加上下文:使用fmt.Errorf
  5. 不要忽略:始终处理错误

准备好学习自定义错误了吗?让我们进入下一章!

最后更新:2026-03-26