Go语言错误处理:try/catch及全面解析从A到Z

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Go语言错误处理:理念与实践



与许多现代语言不同,Go (Golang)不使用经典的try/catch结构。相反,Go开发者遵循“错误即值”(errors as values)的理念。这使得代码更加明确、可预测且安全。在本文中,我们将全面解析Go语言错误处理的各个方面:从基础模式到使用defer、panic和recover的高级技术。



1. 基础:错误就是值



在Go中,错误是一个接口error,只有一个方法Error() string。任何可能失败的函数都会将错误作为最后一个返回值返回。



package main

import ( "errors" "fmt")

// 返回错误的除法函数func divide(a, b float64) (float64, 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 } fmt.Println("结果:", result)}


关键点:if err != nil检查是Go中处理错误的标准方式。没有可能意外“抛出”的隐藏异常。



2. 创建和自定义错误



Go提供了几种创建错误的方式:



  • errors.New() — 简单的文本错误。
  • fmt.Errorf() — 带格式化的错误(支持%w进行包装)。
  • 自定义类型 — 用于传递额外上下文。


带额外数据的自定义错误



type DivisionError struct {    Dividend float64    Divisor  float64    Message  string}

func (e *DivisionError) Error() string { return fmt.Sprintf("%s: %f / %f", e.Message, e.Dividend, e.Divisor)}

func safeDivide(a, b float64) (float64, error) { if b == 0 { return 0, &DivisionError{ Dividend: a, Divisor: b, Message: "除以零", } } return a / b, nil}

func main() { _, err := safeDivide(10, 0) if err != nil { // 类型断言以获取额外字段 var divErr *DivisionError if errors.As(err, &divErr) { fmt.Printf("用%f除以%f时出错: %s", divErr.Dividend, divErr.Divisor, divErr.Message) } }}


使用errors.As()可以检查错误是否为特定类型,并从中提取数据。这类似于其他语言中的instanceof。



3. 错误处理模式:从简单到复杂



Go中有几种成熟的错误处理模式:



3.1. Sentinel errors(哨兵错误)

这些是预定义的错误,可以使用==进行比较。例如:io.EOF。



import (    "errors"    "fmt")

var ErrNotFound = errors.New("未找到元素")

func findUser(id int) (string, error) { if id != 1 { return "", ErrNotFound } return "Alice", nil}

func main() { _, err := findUser(2) if errors.Is(err, ErrNotFound) { fmt.Println("未找到用户,正在创建新用户...") }}


3.2. 错误包装(Wrapping)

从Go 1.13开始,可以使用fmt.Errorf中的%w来包装错误。这保留了错误链。



func readConfig(path string) error {    data, err := os.ReadFile(path)    if err != nil {        return fmt.Errorf("读取配置文件%s: %w", path, err)    }    // ... 处理data                

博客

书籍推荐