导读:本期聚焦于小伙伴创作的《Go中errors.New和fmt.Errorf有什么区别?如何选择错误创建方式》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Go中errors.New和fmt.Errorf有什么区别?如何选择错误创建方式》有用,将其分享出去将是对创作者最好的鼓励。

在Go语言的标准库中,errors包和fmt包都提供了创建错误的函数,其中errors.New和fmt.Errorf是最常用的两个错误创建方式,两者在功能和使用场景上存在明显差异,理解这些差异能帮助开发者更合理地处理程序中的错误。

Go中errors.New和fmt.Errorf有什么区别?如何选择错误创建方式

基础功能对比

errors.New是errors包提供的函数,用于创建一个简单的静态错误,错误内容就是传入的字符串,不支持格式化操作。fmt.Errorf是fmt包提供的函数,支持类似fmt.Sprintf的格式化能力,可以动态拼接错误内容,同时还支持Go 1.13引入的错误包装功能。

两者的基础使用示例如下:

package main

import (
    "errors"
    "fmt"
)

func main() {
    // 使用errors.New创建错误
    err1 := errors.New("连接数据库失败")
    fmt.Println(err1) // 输出:连接数据库失败

    // 使用fmt.Errorf创建错误
    dbAddr := "127.0.0.1:3306"
    err2 := fmt.Errorf("连接数据库%s失败", dbAddr)
    fmt.Println(err2) // 输出:连接数据库127.0.0.1:3306失败
}

核心差异点

1. 是否支持格式化

errors.New仅能接收固定的字符串作为参数,无法动态拼接内容,适合错误内容完全固定的场景。fmt.Errorf支持格式化占位符,比如%s、%d、%w等,可以动态将变量内容拼接到错误信息中,适合错误内容需要包含动态参数的场景。

2. 错误包装能力

errors.New创建的错误是独立的错误实例,不包含其他错误的上下文信息。fmt.Errorf在使用%w占位符时,可以将一个错误包装到新创建的错误中,形成错误链,后续可以通过errors.Is和errors.As判断底层错误类型。

错误包装的示例如下:

package main

import (
    "errors"
    "fmt"
    "os"
)

func readFile() error {
    _, err := os.Open("test.txt")
    if err != nil {
        // 使用%w包装原始错误
        return fmt.Errorf("读取文件失败: %w", err)
    }
    return nil
}

func main() {
    err := readFile()
    if err != nil {
        // 判断底层错误是否为文件不存在错误
        if errors.Is(err, os.ErrNotExist) {
            fmt.Println("文件不存在")
        }
    }
}

3. 错误实例的唯一性

每次调用errors.New都会创建一个新的错误实例,即使传入的字符串完全相同,两个错误也不相等。而fmt.Errorf如果不使用%w包装,创建的错误实例同样是独立的,但是它的核心差异还是在于格式化能力。

错误实例对比示例:

package main

import (
    "errors"
    "fmt"
)

func main() {
    err1 := errors.New("参数错误")
    err2 := errors.New("参数错误")
    fmt.Println(err1 == err2) // 输出:false

    err3 := fmt.Errorf("参数错误")
    err4 := fmt.Errorf("参数错误")
    fmt.Println(err3 == err4) // 输出:false
}

使用场景选择

  • 当错误内容是固定字符串,不需要包含动态参数,也不需要包装其他错误时,优先使用errors.New,比如定义包级别的导出错误变量:
    var ErrInvalidParam = errors.New("无效的参数")
    
  • 当错误内容需要包含动态参数,比如变量值、地址、ID等信息时,使用fmt.Errorf配合对应的格式化占位符拼接内容。
  • 当需要保留底层错误的上下文,方便上层调用者判断原始错误类型时,使用fmt.Errorf配合%w占位符包装错误。

底层实现简单说明

errors.New的实现非常简单,就是创建一个包含传入字符串的errorString结构体实例,该结构体实现了error接口的Error()方法,返回对应的字符串。

fmt.Errorf的实现则复杂很多,它会先解析格式化字符串,处理各个占位符,当遇到%w占位符时,会将对应的错误保存到新创建的错误实例中,形成错误链,支持后续的errors.Is和errors.As查询。

对比维度errors.Newfmt.Errorf
格式化支持不支持支持
错误包装不支持支持(使用%w时)
适用场景固定内容错误、包级别错误定义动态内容错误、需要包装上下文的错误

在实际开发中,不需要刻意区分两者的使用,根据需求选择即可,固定内容用errors.New,需要动态拼接或者包装错误用fmt.Errorf,这样能让错误处理更清晰合理。

errors.Newfmt.ErrorfGo错误创建错误包装修改时间:2026-07-14 12:39:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。