Go语言入门之错误处理

Go语言入门之错误处理

错误处理是开发中必不可少的一个部分,go中的错误一般有两种,一种为error,一种为panic

go语言通常返回一个错误值,然后检查错误值是否为nil,以此判断函数是否执行

1.Error

Go使用error接口来表示一个错误,任何实现此接口的类型都能当做一个错误。

(1)定义

// error 接口的定义
type error interface {Error() string
}

实例

type User struct {Name string
}func genUser() (*User, error) {return nil, errors.New("user == nil")
}
func main() {if u, err := genUser(); err != nil {fmt.Println(err)} else {fmt.Println(u.Name)}
}

使用经验

  • error 应该是函数的最后一个返回值。
  • error 不为 nil 时,不应该对其他返回值有所期待。
  • 只需在error最后出现的位置打印错误即可。

(2)使用

errors.New
func pay(money float64) error {if money < 10 {return errors.New("余额不足")}return nil
}
errors.Is

判断错误是否是某一个特定错误

var MoneyNotEnough = errors.New("余额不足")func pay(money float64) error {if money < 10 {return errors.New("余额不足")}return nil
}func main() {err := pay(5)if errors.Is(err, MoneyNotEnough) {fmt.Println("两个错误一致")} else {// 最后会输出这里fmt.Println("两个错误不一致")}
}

原因: 因为errors.New返回的是一个指针,每次New得到的地址都不同,这种设计可以防止如果两个错误是不同的错误,但是其中的字符串相同,errors.Is不会判断其是一种错误(可能面试会问)

fmt.Errorf
func pay(money float64) error {if money < 10 {return fmt.Errorf("余额不足:%f", money)}return nil
}
errors.As

提取指定类型的错误,判断包装的 error 链中,某一个 error 的类型是否与 target 相同,并提取第一个符合目标类型的错误的值,将其赋值给 target。

// errors.As()用于将error转换为具体的error类型
type MyError struct {Msg string
}func (e *MyError) Error() string {return e.Msg
}var MoneyNotEnough = &MyError{Msg: "余额不足"}func pay(money float64) error {if money < 10 {return MoneyNotEnough}return nil
}func main() {err := pay(5)var myError *MyErrorif errors.As(err, &myError) {fmt.Println("转换成功")fmt.Println(myError.Error())} else {fmt.Println("不是此error类型")}
}

fmt.Errorf():创建一个新的错误。这个函数接受一个格式化字符串和一些参数,返回一个新的错误

// fmt.Errorf()可以将一个错误进行封装,封装后的错误和之前的相等
func main() {originalErr := errors.New("原始错误")//%w 嵌套生成一个新的错误newError := fmt.Errorf("error: %w", originalErr)if errors.Is(newError, originalErr) {fmt.Println("这两个错误相等")}//用于将一个错误对象展开,得到下一层错误对象originalErr1 := errors.Unwrap(newError)if errors.Is(originalErr, originalErr1) {fmt.Println("这两个错误相等")}
}

errors.Join

// errors.Join可以进行多个错误的封装,这是go1.20版本的新特性
func main() {err1 := errors.New("err1")err2 := errors.New("err2")err := errors.Join(err1, err2)if errors.Is(err, err1) {fmt.Println("err is err1")}if errors.Is(err, err2) {fmt.Println("err is err2")}
}

2.Panic

panic会导致程序直接退出。一般只有遇到不可恢复的错误才使用panic

(1)panic报错逻辑

当发生panic时,panic 函数会向上传播到调用它的 goroutine

如果 panic 函数没有被捕获,则会一直向上传播

直到遇到 defer 语句中调用的 recover() 函数

如果找不到recover调用,程序将打印panic的原因并退出

(2)代码实例

func main() {err := pay(5)// defer 延迟调用,在return结束前运行defer func() {// panic会被捕获if err := recover(); err != nil {log.Printf("panic:%+v \n", err)}}()if err != nil {// panic会打印详细的堆栈信息,便于定位错误panic("余额不足")}
}

也可以使用匿名函数处理

func main() {// 使用匿名函数 将需要保护的代码 控制在一定范围func() {err := pay(5)defer func() {if err := recover(); err != nil {log.Printf("panic:%+v \n", err)}}()if err != nil {panic("余额不足")}}()fmt.Println("发生panic后 这里的代码依旧会执行")
}

(3)recover()

  • 用于捕获panic并恢复程序的执行
  • 该函数可以接收一个参数,该参数将存储panic的原因
  • 该函数只能在defer函数中才可以生效,处理panic

(4)注意事项

  • 1.panic报错时recover并不能跨协程捕获,即本协程中的panic不能在其他协程中用recover捕获到
  • 2.如果panic发生在defer函数中则不能用此内recover捕获,因为语句已被中断
  • 3.如果recover在defer函数内的一个函数内,也会捕获失败
  • 4.recover捕获如果有多个panic只会捕获最后一个
  • 5.recover只在defer函数内才可以捕获panic

(5)常见场景

  • 1.运行时错误:例如数组越界,字符串越界,空指针引用,除数为0等等
  • 2.接口相关:接口未实现方法
  • 3.channel相关:向关闭的通道内发送数据,关闭为nil的通道,关闭已经关闭的通道
  • 4.map:给空map赋值,即给nil map写数据,并发读写相同map
  • 4.死锁,所有线程睡眠
  • 5.递归调用导致栈溢出或者死循环
  • 6.无效类型转换,即类型断言失败
  • 7.显示调用某些panic函数表示不可恢复场景

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

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

相关文章

鸿蒙OpenHarmony Native API【drawing_pen.h】 头文件

drawing_pen.h Overview Related Modules: [Drawing] Description: 文件中定义了与画笔相关的功能函数 Since: 8 Version: 1.0 Summary Enumerations Enumeration NameDescription[OH_Drawing_PenLineCapStyle] { [LINE_FLAT_CAP], [LINE_SQUARE_CAP], [LINE_ROUND_…

Exchange Server 中 Exchange 虚拟目录的默认设置

Exchange Server 2016 和 Exchange Server 2019 在服务器安装过程中自动配置多个 Internet Information Services (IIS) 虚拟目录。 以下部分中的表显示了邮箱服务器上客户端访问 (前端) 服务的设置&#xff0c;以及默认的 IIS 身份验证和安全套接字层 (SSL) 设置。 有时为了调…

聚焦智慧出行,TDengine 与路特斯科技再度携手

在全球汽车行业向电动化和智能化转型的过程中&#xff0c;智能驾驶技术正迅速成为行业的焦点。随着消费者对出行效率、安全性和便利性的需求不断提升&#xff0c;汽车制造商们需要在全球范围内实现低延迟、高质量的数据传输和处理&#xff0c;以提升用户体验。在此背景下&#…

从零开始:神经网络(1)——什么是人工神经网络

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 人工神经网络&#xff08;Artificial Neural Network&#xff0c;简称ANN&#xff09;是一种模仿生物神经网络结构和功…

Android SurfaceFlinger——GraphicBuffer初始化(二十九)

在 SurfaceFlinger 中,GraphicBuffer 是一个关键的数据结构,用于封装和管理图形数据的内存缓冲区。它不仅在 SurfaceFlinger 内部使用,也被其他组件如 GPU 驱动、摄像头服务、视频解码器等广泛利用,以实现高效的数据交换和图形渲染。 一、概述 GraphicBuffer 对象封装了一…

从dev分支合并到master分支

git命令从dev分支合并到master分支 1、拉取dev分支的代码 git checkout dev //切换成本地分支 git pull origin dev //拉取远程开发分支 git add . //暂存到本地仓库 git commit -m //增加备注信息 git push origin dev //推送到远程仓库 git checkout master // 切换到maste…

《500 Lines or Less》(5)异步爬虫

https://aosabook.org/en/500L/a-web-crawler-with-asyncio-coroutines.html ——A. Jesse Jiryu Davis and Guido van Rossum 介绍 网络程序消耗的不是计算资源&#xff0c;而是打开许多缓慢的连接&#xff0c;解决此问题的现代方法是异步IO。 本章介绍一个简单的网络爬虫&a…

STM32F0-标准库时钟配置指南

启动 从startup_stm32f0xx.s内的开头的Description可以看到 ;* Description : STM32F051 devices vector table for EWARM toolchain. ;* This module performs: ;* - Set the initial SP ;* - Set t…

使用sqlalchemy查询mysql的JSON字段

使用sqlalchemy查询mysql的JSON字段 在使用SQLAlchemy查询MySQL的JSON字段时,你可以按照以下步骤操作: 假设你有一个包含JSON字段的表格 假设你有一个名为 items 的表格,其中有一个名为 data 的JSON字段。我们来查询这个字段。 1. 定义模型类 首先,你需要定义一个与表…

【Leetcode】十八、动态规划:不同路径 + 最大正方形

文章目录 1、动态规划2、leetcode509&#xff1a;斐波那契数列3、leetcode62&#xff1a;不同路径4、leetcode121&#xff1a;买卖股票的最佳时机5、leetcode70&#xff1a;爬楼梯6、leetcode279&#xff1a;完全平方数7、leetcode221&#xff1a;最大正方形 1、动态规划 只能…

【Java语法基础】4.字符串

4.字符串 字符char无需多言&#xff0c;单引号。 String类 基本操作 String类的访问不能通过数组访问&#xff0c;只能通过API&#xff0c;并且只能访问不能修改&#xff0c;如&#xff1a; String a "hello"; for(int i 0; i < a.length(); i ) {//注意&…

C#开源、简单易用的Dapper扩展类库 - Dommel

项目特性 Dommel 使用 IDbConnection 接口上的扩展方法为 CRUD 操作提供了便捷的 API。 Dommel 能够根据你的 POCO 实体自动生成相应的 SQL 查询语句。这大大减少了手动编写 SQL 代码的工作量&#xff0c;并提高了代码的可读性和可维护性。 Dommel 支持 LINQ 表达式&#xff…

记一次因敏感信息泄露而导致的越权+存储型XSS

1、寻找测试目标 可能各位师傅会有苦于不知道如何寻找测试目标的烦恼&#xff0c;这里我惯用的就是寻找可进站的思路。这个思路分为两种&#xff0c;一是弱口令进站测试&#xff0c;二是可注册进站测试。依照这个思路&#xff0c;我依旧是用鹰图进行了一波资产的搜集&#xff…

SSIS_SQLITE

1.安装 SQLite ODBC 驱动程序 2.添加SQLite数据源 在“用户DSN”或“系统DSN”选项卡中&#xff0c;点击“添加”。选择“SQLite3 ODBC Driver”&#xff0c;然后点击“完成”。在弹出的配置窗口中&#xff0c;设置数据源名称&#xff08;DSN&#xff09;&#xff0c;并指定S…

英迈中国与 Splashtop 正式达成战略合作协议

2024年7月23日&#xff0c;英迈中国与 Splashtop 正式达成战略合作协议&#xff0c;英迈中国正式成为其在中国区的战略合作伙伴。此次合作将结合 Splashtop 先进的远程桌面控制技术和英迈在技术服务与供应链管理领域的专业优势&#xff0c;为中国地区的用户带来更加安全的远程访…

Docker 部署的 GitLab备份和恢复

Docker 部署的 GitLab备份和恢复数据 使用 Docker 部署的 GitLab 可以通过 Docker 命令来进行备份和恢复。以下是具体步骤&#xff1a; 1. 停止 GitLab 容器 在进行备份之前&#xff0c;最好先停止 GitLab 容器以确保数据一致性&#xff1a; docker stop <gitlab_contai…

联想教育电脑硬盘保护同传EDU系统使用简明教程

目录 一、原理概述 二、简明使用方法 1、软件下载 2、开机引导 3、开始安装 4、使用 &#xff08;1&#xff09;进入底层 &#xff08;2&#xff09;进行分区设置 &#xff08;3&#xff09;系统设置 &#xff08;4&#xff09;安装硬盘保护驱动 &#xff08;5&…

前端模块化CommonJS、AMD、CMD、ES6

在前端开发中&#xff0c;模块化是一种重要的代码组织方式&#xff0c;它有助于将复杂的代码拆分成可管理的小块&#xff0c;提高代码的可维护性和可重用性。CommonJS、AMD&#xff08;异步模块定义&#xff09;和CMD&#xff08;通用模块定义&#xff09;是三种不同的模块规范…

《昇思 25 天学习打卡营第 19 天 | 生成式对抗网络(GAN)实践指南 》

《昇思 25 天学习打卡营第 19 天 | 生成式对抗网络&#xff08;GAN&#xff09;实践指南 》 活动地址&#xff1a;https://xihe.mindspore.cn/events/mindspore-training-camp 签名&#xff1a;Sam9029 GAN 模型概述 生成式对抗网络&#xff08;GAN&#xff09;是一种前沿的无…

leetcode-101. 对称二叉树

题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 思路 1) 如果同时root1…