
JetBrains 发布 Go 语言错误处理指南
来源标题:How to Handle Errors in Go
JetBrains 在 Go 博客发布了一篇由社区贡献者 Christoph Berger 撰写的 Go 错误处理指南,介绍错误处理技巧与最佳实践。文章指出 Go 将错误视为值,函数出错时会与其他返回值一并返回错误,调用方负责检查并处理。文章还涵盖逻辑错误、I/O 错误、网络错误、数据校验错误等类型及针对性处理方法。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
面向专业 Go 开发的 IDE 本文最初由社区贡献者 Christoph Berger 发表在 JetBrains 的 Go 指南中,之后已迁移至 JetBrains Go 博客。我们还在 2026 年 8 月更新了本文,以反映 Go 语言的最新变化。 错误处理是 Go 与 Java、C++、JavaScript 和 Python 等流行语言的不同之处之一。在 Go 中,错误就是值。其他语言把错误处理移出代码流程,而 Go 认为错误是程序流程的自然组成部分。如果函数遇到错误,它会将该错误与其他返回值一起返回。调用方有责任检查这个错误并相应地处理它。 一个典型的 Go 包或应用在运行时可能遇到各种类型的错误,包括逻辑错误、I/O 错误、网络错误、数据验证错误等。每一种错误都可能需要特定的错误处理方式。Go 提供了一套工具和技术来处理不同类型的错误。 本文探讨 Go 中错误处理的几个方面。你将学习错误处理的技术和最佳实践、如何应对特定类型的错误,以及如何避免错误处理中的常见错误。 本指南中使用的所有示例都是内联给出的,因此仅阅读这些代码片段就足以理解全貌。不过,如果你想边读边动手修改代码,我们有一个仓库,其中包含发布在 GoLand 博客上不同文章的代码示例。本指南的代码位于 error-handling 目录中。 你可以使用自己喜欢的 IDE,或者安装 GoLand IDE。GoLand 提供免费试用;如果你是 GoLand 新手,这是一个很好的试用机会! 然后,fork 或 clone 包含本指南代码的仓库。 按照以下步骤在 GoLand 中打开代码: 这样你就准备好了!在阅读本指南的过程中,请让 IDE 保持触手可及。 如前所述,Go 中所有的错误处理都基于“错误即值”这一概念。Go 中的错误和其他任何值一样,也是一种值。错误值的类型是 error,这是一个内置类型。但这个类型到底是什么?幸运的是,GoLand 让你可以轻松查看 Go 本身的源代码。 在 Project 窗格中,向下滚动到 External Libraries 部分。展开 Go SDK <已安装版本>,然后展开 builtin.go(因为 error 是内置类型): 如果你无法展开 builtin.go,请选择 Project 窗格中的三点菜单,然后选择 Tree Appearance,并确保勾选了 Show Members: 向下滚动,直到在 builtin.go 下方看到 error 类型,然后单击它。文件 builtin.go 会在编辑器区域打开,并显示 error 类型: type error interface { Error() string error 类型是一个接口,只有一个函数 Error() string。在这里使用接口类型,让你可以通过让自定义类型实现 error 接口,轻松创建自定义错误类型。 在大多数情况下,如果函数遇到错误,它本身并不具备正确处理该错误所需的上下文,因此必须将错误传回给调用方。 例如,参见示例代码(readfile.go)中的 func ReadFile(): func ReadFile(path string) ([]byte, error) { if path == "" { // Create an error with errors.New() return nil, errors.New("path is empty") f, err := os.Open(path) if err != nil { // Wrap the error. // If the format string uses %w to format the error, // fmt.Errorf() returns an error that has the // method "func Unwrap() error" implemented. return nil, fmt.Errorf("open failed: %w", err) defer f.Close() buf, err := io.ReadAll(f) if err != nil { return nil, fmt.Errorf("read failed: %w", err) return buf, nil ReadFile() 检查传入的 path,如果 path 为空,它会创建一个新错误并返回。ReadFile() 原本应返回的数据并不存在;因此,ReadFile() 返回一个 nil 值: if path == "" { return nil, errors.New("path is empty") 按照惯例,如果函数返回错误值,它总是返回值列表中最后一个(最右侧的)值: func ReadFile(path string) ([]byte, error) { 调用 ReadFile() 时,它会返回文件内容,同时返回一个错误值,成功时为 nil,失败时非 nil。通常,返回的错误值会被赋给名为 err 的变量(参见配套仓库中的 main.go): , err := ReadFile("no/file") if err != nil { fmt.Println("Error:", err) 这里不需要 ReadFile() 的调用结果,因为本指南专门研究错误处理。因此,返回值被赋给了空白标识符()。 现在,调用方可以测试错误是否为非 nil,并相应地处理该错误。 Go 新手可能会怀念其他语言提供的 try...catch 机制。不过,Go 有一个能实现类似目的的东西:panic 和 recover。但要注意!与 try...catch 不同,panic 和 recover 不是、也不应该是处理错误的标准方式。只有当错误确实是意料之外的,并且无法处理时,才可以使用 panic。在这种情况下,最好让应用尽早崩溃并重启。你将在后面的最佳实践部分了解更多相关内容。 一个不应发生的错误的例子是:作为字面量字符串给出的正则表达式编译失败。因为正则表达式在编译时就是已知的,开发者本应将其写成有效的表达式,从而确保它在运行时不会编译失败。为了强制这一点,regexp 包提供了一个名为 MustCompile() 的函数。前缀 Must 表示如果该函数无法编译给定的正则表达式,它就会 panic。 为了演示这一点,文件 verifypath.go 包含一个函数,用于验证给定路径是否有效。然而,开发者错误地输入了正则表达式——缺少一个右括号:
(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。