如何在Go中向错误中添加额外的信息

引言

当Go中的函数失败时,该函数将使用error接口返回一个值,以允许调用者处理该失败。在许多情况下,开发人员将使用fmt包中的fmt.Errorf函数来返回这些值。不过,在Go 1.13之前,使用此函数的一个缺点是,您将丢失有关可能导致错误返回的任何错误的信息。为了解决这个问题,开发人员要么使用包来提供一种方法将错误“包装”在其他错误中,要么通过在他们的struct错误类型上实现Error() string方法来创建自定义错误。然而,如果您有许多不需要由调用者显式处理的错误,有时创建这些struct类型可能会很繁琐,因此在Go 1.13中,语言添加了一些功能来更容易处理这些情况。

其中一个功能是能够使用带有error值的fmt.Errorf函数包装错误,该函数稍后可以展开以访问包装后的错误。这将错误包装功能构建到Go标准库中,因此不再需要使用第三方库。

此外,函数errors.Iserrors.As使确定特定错误是否包装在给定错误中的任何位置更容易,还将使您直接访问特定错误,而无需自己拆封所有错误。

在本教程中,你将创建一个程序,使用这些函数在函数返回的错误中包含额外的信息,然后创建你自己的自定义错误struct,以支持包装和解包装功能。

Go中的返回和处理错误

当程序中发生错误时,最好的做法是处理这些错误,让用户永远不会看到它们——但要处理这些错误,你需要首先了解它们。在Go中,你可以通过使用特殊的interface类型(即error接口)从函数中返回有关错误的信息来处理程序中的错误。使用error接口允许任何Go类型作为error值返回,只要该类型定义了Error() string方法。Go标准库提供了为这些返回值创建error的功能,例如fmt.Errorf函数。

在本节中,你将创建一个带有函数的程序,该函数使用fmt.Errorf来返回一个错误,你还将添加一个错误处理程序来检查函数可能返回的错误。如果您想了解有关Go中处理错误的更多信息,请参阅教程,Go中处理错误

许多开发人员都有一个目录来保存当前项目。在本教程中,你将使用一个名为projects的目录。

首先,创建projects目录并导航到它:

mkdir projects
cd projects

projects目录中,创建一个新的errtutorial目录来保存新程序:

mkdir errtutorial

接下来,使用cd命令切换到新目录:

cd errtutorial

进入errtutorial目录后,使用go mod init命令创建一个名为==errtutorial==的新模块:

go mod init errtutorial

创建Go模块后,使用nano或你喜欢的编辑器在errtutorial目录中打开一个名为main.go的文件:

nano main.go

接下来,你将编写一个程序。程序将循环遍历数字13,并使用名为validateValue的函数尝试确定这些数字是否有效。如果数字被确定为无效,程序将使用fmt.Errorf函数生成一个error值并从函数返回。fmt.Errorf函数允许你创建一个error值,其中的错误消息就是你提供给函数的消息。它的工作原理类似于fmt.Printf,但它不是将消息打印到屏幕上,而是将其作为error返回。

然后,在main函数中,将检查错误值是否为nil。如果是nil值,则函数成功并打印valid!消息。如果不是,则打印接收到的错误。

要开始你的程序,将以下代码添加到main.go文件中:

projects/errtutorial/main.go

package mainimport ("fmt"
)func validateValue(number int) error {if number == 1 {return fmt.Errorf("that's odd")} else if number == 2 {return fmt.Errorf("uh oh")}return nil
}func main() {for num := 1; num <= 3; num++ {fmt.Printf("validating %d... ", num)err := validateValue(num)if err != nil {fmt.Println("there was an error:", err)} else {fmt.Println("valid!")}}
}

程序中的validateValue函数接受一个数字,然后根据它是否被确定为有效值返回一个error。在这个程序中,数字1是无效的,并返回错误that's odd。数字2无效,并返回错误uh ohvalidateValue函数使用fmt.Errorf函数来生成要返回的error值。fmt.Errorf函数很方便地返回错误,因为它允许您使用类似于fmt.Printffmt.Sprintf的格式来格式化错误消息,而不需要将string传递给errors.New

main函数中,for循环将开始迭代从13的每个数字,并将值存储在num变量中。在循环体中,调用fmt.Printf将打印程序当前正在验证的数字。然后,它将调用validateValue函数并传入当前正在验证的数字num,并将错误结果存储在err变量中。最后,如果err不是nil,则意味着在验证过程中发生了错误,并使用fmt.Println打印错误消息。错误检查的else子句将打印"valid!"当没有遇到错误时。

保存更改后,使用go run命令运行程序,并将main.go作为errtutorial目录的参数:

go run main.go

运行该程序的输出将表明,对每个数字都运行了验证,数字1和数字2都返回了相应的错误:

Outputvalidating 1... there was an error: that's odd
validating 2... there was an error: uh oh
validating 3... valid!

查看程序的输出时,你会发现程序试图验证所有三个数字。第一次它说validateValue函数返回了that's odd错误,这是1的值所期望的。下一个值2也显示它返回了一个错误,但这次是uh oh错误。最后,3返回nil作为错误值,这意味着没有错误并且数字是有效的。根据validateValue函数的编写方式,任何非12的值都会返回nil错误值。

在本节中,你使用fmt.Errorf来创建从函数返回的error值。我们还添加了一个错误处理程序,以便在函数返回任何error时打印出错误消息。不过,有时候,知道错误的含义可能很有用,而不仅仅是知道错误发生了。在下一节中,你将学习针对特定情况自定义错误处理。

使用哨兵错误处理特定错误

当你从函数中收到一个error值时,最基本的错误处理是检查error值是否为nil。这将告诉你函数是否有错误,但有时你可能希望针对特定的错误情况自定义错误处理。例如,假设你有代码连接到远程服务器,而你得到的唯一错误信息是“you had a error”。你可能想知道这个错误是因为服务器不可用还是连接凭据无效。如果你知道这个错误意味着用户的凭据是错误的,你可能想让用户立即知道。但是,如果错误意味着服务器不可用,您可能需要尝试重新连接几次,然后才能让用户知道。确定这些错误之间的区别可以让你编写更健壮、更友好的程序。

检查特定类型错误的一种方法可能是使用error类型的error方法从错误中获取消息,并将该值与你要查找的错误类型进行比较。想象一下,在你的程序中,当错误值为uh oh时,你想显示一条消息,而不是 there was an error: uh oh。处理这种情况的一种方法是检查Error方法的返回值,如下所示:

if err.Error() == "uh oh" {// Handle 'uh oh' error.fmt.Println("oh no!")
}

检查err.Error()的字符串值,看看它是否为uh oh,就像上面的代码一样,在这种情况下可以工作。但是,如果程序中其他地方的uh oh错误字符串稍有不同,代码就无法工作。检查错误如果需要更新错误消息本身,这种方式也可能导致对代码的重大更新,因为每个检查错误的地方都需要更新。以以下代码为例:

func giveMeError() error {return fmt.Errorf("uh h")
}err := giveMeError</

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/231667.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux--学习记录(3)

G重要编译参数 -g&#xff08;GDB调试&#xff09; -g选项告诉gcc产生能被GNU调试器GDB使用的调试信息&#xff0c;以调试程序编译带调试信息的可执行文件g -g hello.c -o hello编译过程&#xff1a; -E&#xff08;预处理&#xff09; g -E hello.c -o hello.i-S&#xff08;编…

Kubernetes 容器编排(4)

Downward API Downward API 用于在容器中获取 POD 的基本信息&#xff0c;kubernetes原生支持 Downward API提供了两种方式用于将 POD 的信息注入到容器内部&#xff1a; 1.环境变量&#xff1a;用于单个变量&#xff0c;可以将 POD 信息直接注入容器内部。 2.Volume挂载&…

【Docker】Docker安装部署maven私服

文章目录 镜像拉取构建nexus实例登录maven私服如何查看实例初始化的admin密码呢&#xff1f;1.查看容器挂载卷2.找到nexus_nexus_data查看挂载卷详情3.查看admin账号密码4.登录并重置密码 使用nexus私服1.设置settings.xml2.设置idea pom 出现的问题小插曲 镜像拉取 docker pu…

Spring Cloud + Vue前后端分离-第6章 通用代码生成器开发

Spring Cloud Vue前后端分离-第6章 通用代码生成器开发 6-1 代码生成器原理介绍 1.增加generator模块&#xff0c;用于代码生成 2.集成freemarker 通用代码生成器开发 FreeMarker 是一款模版引擎&#xff0c;通过模板生成文件&#xff0c;包括html页面&#xff0c;excel …

Ubuntu 18.04配置NFS服务器以及配置时遇到NFS问题

1.安装相关软件 sudo apt-get install nfs-kernel-server sudo apt-get install nfs-common 2.配置共享目录 2.1修改exports文件 sudo vi /etc/exports在最后添加如下并保存退出 /home/xiaowu/nfs 192.168.31*(rw,sync,no_root_squash,no_subtree_check) /home/xiaowu/nfs…

计算机组成原理(输入输出系统-----程序查询方式)

目录 程序查询方式 一.程序查询方式的流程 1.查询流程 2.程序流程 二.程序查询方式的接口电路 程序查询方式 一.程序查询方式的流程 1.查询流程 单个设备&#xff1a; 如果在传输过程当中只有一个内存和I/O之间数据传输&#xff0c;在执行程序的过程当中CPU会执行出来一…

Windows11编译x265源码生成Visual Studio工程详细步骤

概述 x265是一款开源符合HEVC标准的编码器&#xff0c;也属于VLC项目之一。 由于x265是开源的&#xff0c;因此它得到了广泛的应用和开发。许多开源项目和商业产品都使用x265进行视频压缩处理。同时&#xff0c;x265也支持多种编程语言和平台&#xff0c;使得开发者可以方便地…

Docker与云计算平台集成:AWS、Azure、GCP完全指南

Docker和云计算平台的结合&#xff0c;如AWS&#xff08;Amazon Web Services&#xff09;、Azure&#xff08;Microsoft Azure&#xff09;和GCP&#xff08;Google Cloud Platform&#xff09;&#xff0c;为现代应用的构建和部署提供了巨大的便利性。本文将深入研究如何与这…

02.微服务组件 Eureka注册中心

1.Eureka注册中心 服务提供者与消费者&#xff1a; 服务提供者:一次业务中&#xff0c;被其它微服务调用的服务。(提供接口给其它微服务)服务消费者:一次业务中&#xff0c;调用其它微服务的服务。&#xff08;调用其它微服务提供的接口)一个服务是消费者还是提供者&#xff…

第二百一十三回

文章目录 概念介绍实现方法示例代码经验总结 我们在上一章回中介绍了组件之间共享数据相关的内容&#xff0c;本章回中将介绍全局共享数据.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在上一章回中介绍了使用InheritedWidget组件共享数据的方法&#xff0c…

Redis设计与实现之Lua 脚本

目录 一、 Lua 脚本 1、初始化 Lua 环境 2、脚本的安全性 3、脚本的执行 4、 EVAL 命令的实现 定义 Lua 函数 执行 Lua 函数 5、 EVALSHA 命令的实现 二、 小结 一、 Lua 脚本 Lua 脚本功能是 Reids 2.6 版本的最大亮点&#xff0c;通过内嵌对 Lua 环境的支持&#xf…

Mysql之约束上篇

Mysql之约束上篇 约束的概述为什么需要约束什么是约束约束的分类 非空约束作用关键字特点添加非空约束删除非空约束 唯一性约束关键字特点添加唯一约束关于复合唯一约束删除唯一约束查看索引 主键约束(非空唯一性约束)作用关键字特点添加主键约束关于复合主键删除主 约束的概述…

探索拉普拉斯算子:计算机视觉中用于边缘检测和图像分析的关键工具

一、介绍 拉普拉斯算子是 n 维欧几里得空间中的二阶微分算子&#xff0c;表示为 ∇。它是函数梯度的发散度。在图像处理的上下文中&#xff0c;该运算符应用于图像的强度函数&#xff0c;可以将其视为每个像素具有强度值的二维信号。拉普拉斯算子是计算机视觉领域的关键工具&am…

了解 SBOM (软件物料清单)

近年来&#xff0c;开源软件在开发中的采用激增&#xff0c;目前已占已构建软件的高达 90%。它在全球公司中的受欢迎程度源于成本节约和产品上市时间的加快。然而&#xff0c;在集成开源软件组件时&#xff0c;有一个关键的方面需要考虑。 Synopsys 报告84% 的商业和专有代码库…

Qt-QTransform介绍与使用

QTransform是一个用于二维坐标系转换的类。我们知道Qt的坐标系是左上角为原点&#xff0c;x轴向右&#xff0c;y轴向下&#xff0c;屏幕上每个像素代表一个单位&#xff0c;那么&#xff0c;如果我们想要在屏幕上建立自己的坐标系用于绘制&#xff0c;就需要借助QTransform。 …

Guitar Pro8.1最新2024中文免激活版下载(附教程)

Guitar Pro 8是一款功能强大的指法阅读器和编辑器&#xff0c;它允许您编辑吉他、贝斯和尤克里里的乐谱和指法谱&#xff0c;并为鼓或钢琴创建背景音轨。轻松创建、播放和共享您的标签&#xff01;快速的进行乐谱播放并进行练习&#xff0c;也可以进行编辑操作&#xff0c;允许…

Gumbel 重参数化相关性质证明

Gumbel 的采样过程&#xff1a; z a r g m a x i { g i l o g ( π i ) } , g i − l o g ( − l o g ( u i ) ) , u i ∼ U ( 0 , 1 ) zargmax_i \{g_i log(\pi_i)\}, g_i -log(-log(u_i)),u_i\sim U(0, 1) zargmaxi​{gi​log(πi​)},gi​−log(−log(ui​)),ui​∼U(0…

机器学习---推荐系统案例(一)

一、推荐系统-数据处理流程 推荐系统数据处理首先是将Hive中的用户app历史下载表与app浏览信息表按照设备id进行关联&#xff0c;然后将关联数据使用python文件进行处理&#xff0c;将数据预处理为label和feature两列的临时数据&#xff0c;后期经过处理转换成逻辑回归 模型的…

【经典LeetCode算法题目专栏分类】【第5期】贪心算法:分发饼干、跳跃游戏、模拟行走机器人

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 分发饼干 class Solutio…

【Qt之Quick模块】1. 概述及Quick应用程序创建流程

概述 Qt的Quick模块是用于创建现代化、动态和响应式用户界面的工具集。它是基于QML&#xff08;Qt Meta-Object Language&#xff09;和JavaScript的。 QML是一种声明性的语言&#xff0c;用于描述用户界面的结构和行为。它使用层叠样式表&#xff08;CSS&#xff09;的语法来…