【Hello Go】Go语言异常处理

Go语言异常处理

  • 异常处理
    • error接口
    • panic
    • recover
      • 延时调用错误问题

异常处理

error接口

Go语言引入了一个关于错误处理的标准模式 它是Go语言内建的接口类型 它的定义如下

type error interface {Error() string
}

Go语言的标准库代码包errors为用户提供了以下方法

package errors
type errorString struct {
text string
}func New(text string) error {
return &errorString{text}
}func (e *errorString) Error() string {
return e.text
}

另一个可以生成 error 类型值的方法是调用 fmt 包中的 Errorf 函数:

package fmt
import "errors"
func Errorf(format string, args ...interface{}) error {
return errors.New(Sprintf(format, args...))
}

下面是代码示例

import (
"errors"
"fmt"
)
func main() {
var err1 error = errors.New("a normal err1")
fmt.Println(err1) //a normal err1
var err2 error = fmt.Errorf("%s", "a normal err2")
fmt.Println(err2) //a normal err2
}

一般来说 错误处理位于函数的最后 下面是代码示例

import (
"errors"
"fmt"
)func Divide(a, b float64) (result float64, err error) {
if b == 0 {
result = 0.0
err = errors.New("runtime error: divide by zero")
return
}
result = a / b
err = nil
return
}
func main() {
r, err := Divide(10.0, 0)
if err != nil {
fmt.Println(err) //错误处理 runtime error: divide by zero
} else {
fmt.Println(r) // 使用返回值
}
}

panic

通常情况下 我们报错时可以返回一个error值

但是如果我们遇到了不可恢复的异常 比如说数组越界访问 空指针引用等

此时就会引发panic异常


一般而言 当当panic异常发生的时候 该程序会立刻停止运行 并且立即执行在该goroutine(我们这里暂时理解为线程)下的defer的函数

随后 程序崩溃并输出日志信息 日志信息包括panic value和函数调用的堆栈跟踪信息

此外需要注意的是 并不是所有panic异常都来自运行时 我们主动调用panic函数也会引起panic异常

panic函数可以接受任何值作为参数

func panic(v interface{})

下面是代码和结果演示

package mainimport "fmt"func testA() {fmt.Println("testA ~~~")
}func testB() {panic("panic error ~~~")
}func testC() {fmt.Println("testC ~~~")
}func main() {testA()testB()testC()
}

我们发现前面的函数顺序执行完毕之后到panic异常

当然如果我们自己主动写点bug比如说数组越界 除0错误 效果也是一样的

recover

程序运行时 只要引发了panic异常就会引发程序崩溃 这是我们怎么都不愿意看到的

因此Go语言给我们提供了一种专门拦截运行时异常的内建函数 – recover

它可以使程序从panic状态恢复并获得流程控制权

注意:!!! recover只有在defer调用的函数中有效

如果说调用了内置函数decover并且定义该defer语句的函数发生了panic异常 recover会从panic中恢复 并且返回panic和vlaue 导致panic异常的函数不会正常运行 但会正常返回

但是在未发生panic时调用recover recover会返回nil

代码演示如下

package mainimport "fmt"func testA() {fmt.Println("testA ~~~")
}func testB() (err error) {defer func() {if x := recover(); x != nil {// 此时panic和value被添加到x中err = fmt.Errorf("internal error: %v", x)}}()panic("panic error ~~~")return err
}func testC() {fmt.Println("testC ~~~")
}func main() {testA()err := testB()fmt.Println(err)testC()
}

我们依旧是在test2中主动调用了panic异常

只不过我们在前面延时调用了一个匿名函数

	defer func() {if x := recover(); x != nil {// 此时panic和value被添加到x中err = fmt.Errorf("internal error: %v", x)}}()

在这个匿名函数中我们调用了recover函数 并且接受了err

最终我们可以发现我们的程序正常运行下去了

在这里插入图片描述

延时调用错误问题

如果我们在延时调用中也引发了panic异常 那么该panic异常可以被后续延时调用的recover捕获

代码和结果演示如下

func test() {defer func() {fmt.Println(recover())}()defer func() {panic("test2")}()panic("test1")
}func main() {test()
}

此时我们的recover捕获的错误就不是test1 而是 test2

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

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

相关文章

可拖动、可靠边的 popupWindow 实现

0 背景 开发要实现一个可以拖动的圆角小窗&#xff0c;要求松手时&#xff0c;哪边近些靠哪边。并且还规定了拖动范围。样式如下&#xff1a; 1 实现 首先把 PopupWindow 的布局文件 pop.xml 实现 <?xml version"1.0" encoding"utf-8"?> <R…

马斯克的SpaceX星舰又炸了!发射不久后失联自毁

就在几小时前&#xff0c;马斯克旗下SpaceX 发射了有史以来最强大的星舰&#xff0c;但在发射后不久发生爆炸。 在这次发射尝试中&#xff0c;星舰一二级成功进行了分离&#xff0c;但二级助推器和星舰都发生了快速意料之外的解体。在发射半小时后&#xff0c;SpaceX 宣布二级自…

自动驾驶学习笔记(十)——Cyber通信

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 Cyber通信 编写代码 编译程序 运行…

开源供应链管理系统 S2B2B2C系统方案及源码输出

这个开源供应链管理系统提供针对企业供应链管理需求的开放源代码解决方案。通过开源供应链管理系统&#xff0c;企业能够实现对供应商、进销存和物流配送等方面的全面管理和优化&#xff0c;涵盖了从供应商选择到门店到消费者服务交付的整个流程。开源系统使企业能够根据自身需…

软件测试技术之地图导航的测试用例

外观测试 屏幕显示不能有花屏、黑点和闪屏&#xff0c;清晰度、亮度、颜色要正常。 检测所有按键都能起到相应作用&#xff0c;是否手感不良。 UI显示状态、颜色、清晰度、效果。 控制&#xff1a;放大&#xff0c;缩小&#xff0c;音量调节功能测试。 交叉路口查询测试&am…

Python大数据之linux学习总结——day11_ZooKeeper

ZooKeeper ZK概述 ZooKeeper概念: Zookeeper是一个分布式协调服务的开源框架。本质上是一个分布式的小文件存储系统 ZooKeeper作用: 主要用来解决分布式集群中应用系统的一致性问题。 ZooKeeper结构: 采用树形层次结构&#xff0c;ZooKeeper树中的每个节点被称为—Znode。且树…

GitHub如何删除仓库

GitHub如何删除仓库 删除方法第一步第二步第三步 删除方法 第一步 在仓库的界面选择Settings 第二步 选择General,页面拉到最后。 第三步 删除仓库。

【Python数据结构与算法】——(线性结构)精选好题分享,不挂科必看系列

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:<<Python数据结构与算法专栏>>&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 时间复杂度大小比较 1.time complexity of algorithm A is O(n^3) while algorithm B is O(2^n). Which o…

340条样本就能让GPT-4崩溃,输出有害内容高达95%?OpenAI的安全防护措施再次失效

仅需340个示例微调GPT-4&#xff0c;即可绕过安全限制&#xff0c;让模型说出“枪支改装方法”、“生化武器制作过程”等有害内容&#xff1f; OpenAI的安全防护措施再次失效&#xff0c;攻击的成功率高达95%&#xff01; 近日&#xff0c;美国顶尖大学UIUC与斯坦福联合对GPT…

LinkWeChat V4.9.8 版本发布

LinkWeChat v4.9.8 已经发布&#xff0c;基于企业微信的 SCRM 系统 LinkWeChat 是国内首个基于企业微信的开源 SCRM&#xff0c;在集成了企微强大的开放能力的基础上&#xff0c;进一步升级拓展灵活高效的客户运营能力及多元化精准营销能力&#xff0c;让客户与企业之间建立强…

基于RK3588全高端智能终端机器人主板

一、小尺寸板型设计 该款主板为小型板&#xff0c;尺寸仅为125*85mm&#xff0c;更小更紧凑&#xff0c;可完美适应各类高端智能自助终端&#xff1b; 二、八核高端处理器 采用RK3588S八核64位处理器&#xff0c;8nm LP制程&#xff0c;主频最高达2.4GHz&#xff0c;搭载Andr…

基于springboot实现应急救援物资管理系统项目【项目源码】计算机毕业设计

基于springboot实现应急救援物资管理系统演示 JAVA简介 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&a…