(译)Go1.13中处理错误

Damien Neil 和 Jonathan Amsterdam, 2019 年 10 月 17 日, 原文地址: https://go.dev/blog/go1.13-errors 介绍 在过去的十年中,Go 将 “错误作为值” 来处理 ,这对我们很有帮助。尽管标准库对错误的支持很少 —— 只有 errors.New 和 fmt.Errorf 函数,它们产生的错误只包含一条消息 —— 内置 error 接口允许 Go 程序员添加他们想要的任何信息。它所需要的只是一个实现 Error 方法的类型: 1type QueryError struct { 2 Query string 3 Err error 4} 5 6func (e *QueryError) Error() string { return e.Query + ": " + e.Err.Error() } 像这样的错误类型无处不在,它们存储的信息千差万别,从时间戳到文件名再到服务器地址。通常,该信息包括另一个较低级别的错误以提供额外的上下文。 一个错误包含另一个错误的模式在 Go 代码中非常普遍,经过 https://go.dev/issue/29934[广泛讨论] 后,Go 1.13 添加了对它的明确支持。这篇文章描述了提供该支持的标准库的新增内容:errors 包中的三个新函数,以及 fmt.Errorf. 在详细描述更改之前,让我们回顾一下在该语言的先前版本中如何检查和构造错误。 Go 1.13 之前的错误 检查错误 Go 错误是值。程序以几种方式根据这些值做出决策。最常见的是比较错误以 nil 查 看操作是否失败。 1if err != nil { 2 // something went wrong 3} 有时我们将错误与已知的 标记 值进行比较,以查看是否发生了特定错误。 1var ErrNotFound = errors.New("not found") 2 3if err == ErrNotFound { 4 // something wasn't found 5} 错误值可以是满足语言定义 error 接口的任何类型。程序可以使用类型断言或类型开关将错误值视为更具体的类型。 ...

2023-05-05 · 5 min · 874 words · Hank

(译)Go错误是值

Rob Pike,2015 年 1 月 12 日 ,原文地址: https://go.dev/blog/errors-are-values Go 程序员(尤其是刚接触该语言的程序员)讨论的一个共同点是如何处理错误,这些讨论最终往往都将回归于无数次出现的代码片段: 1if err != nil { 2 return err 3} 如上所示,但我们最近扫描了所有我们能找到的开源项目,发现这个片段每页或每两页只出现一次,比某些人认为的要少。尽管如此,许多程序员仍然认为必须键入如下代码来处理错误: 1if err != nil 一直以来,人们觉得一定有什么地方出了问题,而明显的目标就是 Go 本身。 这是不幸的、误导性的,而且很容易纠正。也许刚接触 Go 的程序员会问,“我该如何处理错误?”,然后学习这种模式,最后就此打住。在其他语言中,可能会使用 try-catch 块或其他类似机制来处理错误。因此,程序员认为,我在我的旧语言中可以使用 try-catch 时,但在 go 中我只能输入 if err != nil 来处理错误。随着时间的推移,Go 代码收集了许多这样的片段,结果感觉很笨拙。 不管这种解释是否成立,很明显这些 Go 程序员忽略了关于错误的一个基本观点: 错误是值。 可以对值进行编程,并且由于错误是值,因此可以对错误进行编程。 当然,涉及错误值的常见语句是测试它是否为 nil,但是错误值可以做无数其他事情,应用其中一些其他事情可以使您的程序更好,从而消除大部分样板代码,避免多次使用 if 语句检查每个错误。 一个简单示例是 bufio 包中的 https://go.dev/pkg/bufio/#Scanner[`Scanner`]。它的 https://go.dev/pkg/bufio/#Scanner.Scan[`Scan`] 方法执行底层 I/O,这当然可能导致错误。然而,该 Scan 方法根本不会暴露错误。相反,它返回一个布尔值和一个单独的方法,在扫描结束时运行,报告是否发生错误。客户端代码如下所示: 1scanner := bufio.NewScanner(input) 2for scanner.Scan() { 3 token := scanner.Text() 4 // process token 5} 6if err := scanner.Err(); err != nil { 7 // process the error 8} 当然,有一个 nil 检查错误,但它只出现并执行一次。假设将该 Scan 方法改为: ...

2023-04-30 · 2 min · 389 words · Hank

(译)Go模块:管理依赖项

原文地址: https://go.dev/doc/modules/managing-dependencies 当您的代码使用外部包时,这些包(作为模块分发)成为依赖项。随着时间的推移,您可能需要升级或更换它们。Go 提供了依赖管理工具,可帮助您在合并外部依赖项时确保 Go 应用程序的安全。 本文介绍如何执行一些任务来管理您代码中的依赖项,您可以使用 Go tools 执行其中的大部分操作。本主题还介绍了如何执行其他一些您可能会觉得有用的依赖相关任务。 // TODO 翻译后修改连接 相关阅读:: 如果您不熟悉模块和依赖,请查看 https://go.dev/doc/tutorial/getting-started[入门教程] 以获得简要介绍。 使用该 go 命令管理依赖项有助于确保您的需求保持一致,并且您的 go.mod 文件的内容是有效的。有关命令的参考,请参阅 https://go.dev/cmd/go/[go命令文档]。您还可以通过键入 go help 命令名称从命令行获取帮助,如go help mod tidy`. 使用 Go 命令更改依赖项时会编辑 go.mod 文件。有关文件内容的更多信息,请参阅 https://go.dev/doc/modules/gomod-ref[go.mod 文件参考文档]。 让您的编辑器或 IDE 能够感知 Go 模块可以让您更轻松地管理它们。有关支持 Go 的编辑器的更多信息,请参阅 https://go.dev/doc/editors.html[编辑器插件和 IDE]。 本主题不描述如何开发、发布和版本模块以供其他人使用。有关更多信息,请参阅 https://go.dev/doc/modules/[开发和发布模块]。 使用和管理依赖项的工作流程 您可以通过 Go tools 获取和使用有用的包。在 https://pkg.go.dev/[pkg.go.dev] 上,您可以搜索您觉得有用的包,然后使用 go 命令将这些包导入您自己的代码中以调用它们的功能。 下面列出了最常见的依赖管理步骤: 在 https://pkg.go.dev/[pkg.go.dev]上 «查找和导入包, 查找有用的包»。 «查找和导入包, 在代码中导入所需的包»。 将您的代码添加到模块以进行依赖跟踪(如果它不在模块中)。请参阅 «代码中启用依赖项跟踪, 启用依赖项跟踪» [«添加依赖项, 添加外部包作为依赖项»,以便您可以管理它们。 随着时间的推移,根据需要 «升级或降级依赖项, 升级或降级依赖版本»。 依赖项作为模块管理 在 Go 中,依赖项作为包含导入包的模块来管理。此过程由以下功能支持: ...

2023-04-19 · 4 min · 665 words · Hank