← Backend / Go / 基础专题

20_错误处理defer与panic

按层处理错误,正确关闭资源并理解 panic 的适用边界。

Go 基础专题 20:错误处理、defer 与 panic

学习目标:按层处理错误,正确关闭资源并理解 panic 的适用边界。

核心知识

Go 用普通返回值 error 表达预期可发生的失败。调用后先检查 err != nil,再使用结果。包装错误时用 fmt.Errorf("读取配置: %w", err) 保留原因,调用方可用 errors.Is 或 errors.As 分类。错误消息一般描述上下文,不要在每层重复打印同一错误。

package main

import (
    "fmt"
    "os"
)

func read(path string) ([]byte, error) {
    data, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("读取 %s: %w", path, err)
    }
    return data, nil
}

func main() {
    _, err := read("missing.txt")
    if err != nil {
        fmt.Println(err)
    }
}

defer 把调用推迟到当前函数返回前,常用于 file.Close() 或解锁。多个 defer 按后进先出执行;其参数在遇到 defer 时求值。panic 表示严重且通常不可在当前层正常恢复的问题,不应用来代替普通输入错误。recover 只对同一 goroutine 的延迟函数中的 panic 有效。

关闭可写文件可能返回错误,不能总是忽略;关键持久化操作需要检查关闭或同步结果。测试时可以从错误链判断原因,而不依赖完整错误文本。

逐步理解

把错误处理分成三层:底层附加操作上下文,中间层决定是否可恢复,入口层决定怎样展示。defer 在函数返回前执行,适合关闭已成功打开的资源;打开失败时还没有可关闭对象。panic 通常意味着程序无法按当前契约继续,普通文件不存在和输入非法都应使用 error。

动手练习

练习:把解析失败包装成“读取年龄”上下文。答案要点:fmt.Errorf("读取年龄: %w", err)。