13 Go的错误处理

概述

        在上一节的内容中,我们介绍了Go的接口,包括:定义接口、实现接口、使用接口、空接口等。在本节中,我们将介绍Go的错误处理。在Go语言中,错误处理是一种重要的编程模式,它用于处理可能出现的错误或异常情况。Go语言采用了一种简洁而直接的错误处理方式,通过使用内置的error类型和约定的返回值,开发人员可以有效地处理和传递错误信息。

errors包

        Go语言中的errors包主要用于进行错误处理,它提供了一些简单的接口和函数,用于创建和操作错误值。下面,我们介绍errors包中一些常见函数的使用方法。

        创建错误:可以使用errors.New()函数来创建一个简单的错误值。它接受一个字符串参数,用于表示错误信息。比如:

          err := errors.New("something is wrong")

        包装错误:可以使用errors.Wrap()函数来包装一个错误值。它接受一个错误值和一个字符串参数,返回一个新的错误值,其中包含了原始错误的详细信息。比如:

          err := errors.Wrap(originalError, "something is wrong")

        获取错误信息:可以使用errors.Unwrap()函数来获取包装错误中的原始错误。它接受一个错误值,返回原始错误。比如:

          originalErr := errors.Unwrap(err)

        判断错误类型:可以使用errors.Is()函数来判断一个错误是否属于特定的类型。它接受一个错误值和一个类型参数,返回一个布尔值表示是否匹配。比如:

          if errors.Is(err, io.EOF)

        错误格式化:可以使用errors.Errorf()函数来创建一个格式化的错误值。它接受一个格式化字符串和变量参数,类似于fmt.Sprintf()函数。比如:

          err := errors.Errorf("something is wrong: %s", errorMessage)

返回错误

        在Go语言中,通常将函数的最后一个返回值定义为error类型,用于指示函数执行过程中是否发生了错误。如果函数执行成功,该错误值为nil;如果函数执行失败,则将相应的错误值赋给错误变量。这种约定使得函数的调用者可以轻松地检查函数是否返回了错误,并根据需要采取相应的处理措施。

        在下面的示例代码中,divide函数接受两个float64类型的参数,并返回一个float64类型的结果和一个error类型的错误。当除数为零时,函数会返回一个非零的错误值,用于描述错误信息。在main函数中,我们通过检查错误变量err是否为nil来判断函数是否执行成功。如果err不为nil,则表示函数执行失败,并打印相应的错误信息;否则,打印函数执行的结果。

package mainimport "fmt"
import "errors"func divide(a, b float64) (float64, error) {if b == 0 {return 0, errors.New("divisor cannot be zero")}return a / b, nil
}func main() {result, err := divide(10, 2)if err != nil {fmt.Println("Error:", err)} else {// 输出:Result: 5fmt.Println("Result:", result)}result, err = divide(10, 0)if err != nil {// 输出:Error: divisor cannot be zerofmt.Println("Error:", err)} else {fmt.Println("Result:", result)}
}

        除了直接返回错误值外,还可以使用多返回值的方式在函数内部进行错误处理。在下面的示例代码中,我们使用一个额外的变量来指示函数是否执行成功。

package main  import "fmt"
import "errors"func divide(a, b float64) (float64, bool, error) {if b == 0 {return 0, false, errors.New("divisor cannot be zero")}if b == 1 {return 0, false, nil}return a / b, true, nil
}  func main() {result, success, err := divide(10, 1)if err != nil {fmt.Println("Error:", err)} else if !success {// 输出:divisor cannot be 1fmt.Println("divisor cannot be 1")} else {fmt.Println("Result:", result)}
}

抛出异常

        在Go语言中,抛出异常可以使用panic函数。panic函数是一个内置函数,用于表示发生了一个无法恢复的错误。当panic函数被调用时,当前函数的执行会立即停止,并且向上递归调用栈,直到找到适当的defer语句或函数返回。

        panic函数通常用于处理无法处理的错误情况,比如:内存溢出、空指针引用等。当panic函数被调用时,它会传递一个字符串作为参数,表示发生错误的原因,这个字符串可以被捕获并用于错误处理或日志记录。

        在下面的示例代码中,我们用panic函数抛出了异常。在执行panic函数之前,会打印输出字符串“before panic”。在执行panic函数之后,main函数的执行会立即停止,故不会继续执行后面的打印语句。

package mainimport "fmt"func main() {// 输出:before panicfmt.Println("before panic")// 抛出异常panic("an exception occured")// 以下语句不会被执行fmt.Println("after panic")
}

捕获异常

        在Go语言中,捕获异常可以使用recover函数和defer关键字。

        recover函数是一个内建函数,用于从一个panic异常中恢复并继续执行程序。当程序遇到panic时,它会中断当前的执行流程并开始向上层调用栈传播panic,直到被捕获或程序终止。recover函数允许在defer关键字修饰的函数中捕获并处理panic异常,以便程序可以继续执行而不会终止。

        defer关键字用于延迟执行一个函数调用,直到包含它的函数返回之前执行。被defer修饰的函数调用会被推入一个栈中,等到包含它的函数返回时,该函数调用才会被从栈中弹出并执行。defer关键字通常用于在函数返回之前执行一些清理操作,比如:关闭文件、释放资源、打印日志等。它可以用于确保在函数执行结束时,相关的资源被正确释放,避免资源泄漏问题。

        注意:recover函数只能在defer函数中使用,不能在其他上下文中使用。当在defer函数中调用recover时,它会停止panic传播并返回panic的值(如果有的话)。如果没有panic发生,recover函数会返回nil。

        在下面的示例代码中,我们使用defer关键字和匿名函数来创建一个defer函数。在defer函数中,我们调用recover函数来捕获panic异常。如果有panic发生,我们会打印出相应的错误信息。

package mainimport "fmt"func main() {defer func() {if r := recover(); r != nil {// 捕获到异常,输出:an exception caught: an exception occuredfmt.Println("an exception caught:", r)}}()// 输出:before panicfmt.Println("before panic")// 抛出异常panic("an exception occured")// 以下语句不会被执行fmt.Println("after panic")
}

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

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

相关文章

AutoSAR CANIF层配置代码分析

CAN物理控制单元 配置: 生成的代码: CanIf_CtrlStates 解析 类型: typedef union CanIf_CtrlStatesUTag {CanIf_CtrlStatesType raw[3];CanIf_CtrlStatesStructSType str; }CanIf_CtrlStatesUType;typedef struct sCanIf_CtrlStatesType {C…

陪诊系统搭建部署和功能,让就医更便捷和舒适

陪诊系统是一种基于智能手机平台的专门为就医提供陪伴服务的软件。该应用程序包含多种功能,包括提供的医疗知识、行为规范和陪伴服务。它不仅可以帮助用户规划就医时间、预约医生、清楚病情、解答疑问等,还可以在就医时为用户提供实时的陪伴和指导&#…

py 开启异步

在Python中,可以使用异步编程技术来开启异步操作。Python提供了多种异步编程库,其中最常用的是asyncio库。 以下是一个简单的示例,演示如何使用asyncio库来开启异步操作: import asyncioasync def my_coroutine(task):await tas…

论文阅读:JINA EMBEDDINGS: A Novel Set of High-Performance Sentence Embedding Models

Abstract JINA EMBEDINGS构成了一组高性能的句子嵌入模型,擅长将文本输入转换为数字表示,捕捉文本的语义。这些模型在密集检索和语义文本相似性等应用中表现出色。文章详细介绍了JINA EMBEDINGS的开发,从创建高质量的成对(pairwi…

WEB 自动化神器 TestCafe(一)—安装和入门篇

今天小编给大家带来WEB 自动化神器 TestCafe(一) —安装和入门篇 一、TestCafe 介绍: TestCafe 是一款基于 Node.js 的端到端 Web 自动化测试框架,支持 TypeScript 或 JavaScript 来编写测试用例,运行用例,并生成自动化测试报告。…

Flutter笔记:目录与文件存储以及在Flutter中的使用(上)

Flutter笔记 目录与文件存储以及在Flutter中的使用(上) 文件系统基础知识与路径操作 作者:李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 :291148484163.com 本文地址:h…

Navicat DML 操作

在表格种插入 列信息 -- 修改数据 update 表名 set 列名 值1, 列名值2,[where 条件]; -- 注意:如果update语句没有加where 表里对应行的全部信息都会被改; -- 删除数据 delecte from 表名 [where 条件]; 未删除前: 执行删除后为: DQL - 条…

全志XR806基于http的无线ota功能实验

XR806不仅硬件功能多,XR806也提供了功能极其丰富的SDK,几天体验下来非常容易上手。常见的功能几乎都有相应的cmd或demo实现,HAL也做得非常全面,非常适合快速开发。这一点超级好评!本文章要实现的无线OTA也基于该SDK。 …

【已解决】移动号码在移动网上营业厅更换为8元保号套餐

有很多人的副卡基本是为了接收银行卡短信,平时基本不打电话和用流量,每个月固定消费在18-30左右,很浪费。今天发现在网上营业厅就可以修改8元保号套餐,分享给大家。 保号套餐 有以下两种: 解决办法: 1、…

1688API接口接入|阿里1688-B类电商基础链路专业化体验升级

新挑战,新契机! 当下整个互联网的竞争环境的变化为我们带来新的机遇和挑战。1688作为连接中小生产商、贸易商和零售商的源头货源首选平台,持续不断地为B类买家提供更专业的服务和更优质的源头厂货供给,打造核心竞争力。 面对新的…

客户端性能优化实践

背景 双十一大促时,客户客服那边反馈商品信息加载卡顿,在不断有订单咨询时,甚至出现了商品信息一直处于加载状态的情况,显然,在这种高峰期接待客户时,是没法进行正常的接待工作的。 起初,页面一…

程序员请放下你的技术情节,与你的同伴一起进步关心业务

如果说掌握一门赖以生计的技术是技术人员要学会的第一课的话, 那么我觉得技术人员要真正学会的第二课,不是技术,而是业务、交流与协作,学会关心其他工作伙伴的工作情况和进展。 为什么这么说呢? 因为技术人员太容易陷…

计算机视觉与机器学习D1

计算机视觉简介 技术背景 了解人工智能方向、热点 目前人工智能的技术方向有: 1、计算机视觉——计算机视觉(CV)是指机器感知环境的能力;这一技术类别中的经典任务有图像形成、图像处理、图像提取和图像的三维推理。物体检测和人脸识别是其比较成功…

apache 基线安全加固操作

本文档适用于Apache服务器。本规范明确了Apache服务器安全配置方面的基本要求。 账号管理、认证授权 ELK-Apache-01-01-01 编号 ELK-Apache-01-01-01 名称 以特定用户运行服务 实施目的 以特定用户运行服务,不要使用系统管理员账号启动APACHE 问题影响 越权使用造成非…

Kotlin--1.基础语法

目录 一.概念 二.基本语法 1.入门案例 2.变量声明 3.数据类型 4.字符串 (1)访问字符串 (2)字符串长度 (3)字符串函数 (4)比较字符串 (5)在字符串中查找字符串 (6)字符串模板 5.if-else 6.when 7.数组 8.范围 三.函数 1.实例 2.多个参数 3.返回值 一.概念 Kot…

客服中心的客户关系管理核心功能

根据国外的调查,拥有客服中心的运营机构,可以保持85%左右的客户忠诚度,而接受过专业培训的客户中心可以将客户忠诚度提高到99%。客服中心作为客户关系管理的前沿,通过提供服务、实时沟通、搜集与分析客户信息、预测客户需求来提升…

数据结构与算法-生成树与最小生成树

生成树与最小生成树 🎈1.生成树与最小生成树🔭1.1生成树与最小生成树的概念🔭1.2最小生成树的生成准则🔭1.3两种最小生成树算法🏆1.3.1Kruskal算法🏆1.3.2Prim算法 🎈2.有向无环图及其应用&…

【如何学习Python自动化测试】—— 时间等待

3 、 时间等待 在做自动化测试时,难免会碰到一些问题,比如你在脚本中操作某个对象时, 页面还没有加载出来,你的操作语句已经被执行,从而导致脚本执行失败,针对这样的问题 webdriver 提供了等待操作&#xf…

virtuoso 后仿 ADE L error

ADE后仿时出现error ERROR (SFE-23): "input.scs" 299: The instance _57_D32_noxref is referencing an undefined model or subcircuit, parasitic_nwd. Either include the file containing the definition of parasitic_nwd, or define parasitic_nwd before run…