文档章节

Go函数—— defer && panic && recover 处理异常

秋风醉了
 秋风醉了
发布于 2016/07/09 16:27
字数 1096
阅读 28
收藏 0
点赞 0
评论 0

Go函数—— defer && panic && recover 处理异常

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的Exception处理:defer, panic, recover。

这几个异常的使用场景可以这么简单描述:Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。

package main

import (
	"fmt"
)

func main() {

	defer func() { // 必须要先声明defer,否则不能捕获到panic异常
		if err := recover(); err != nil {
			fmt.Println(err) // 这里的err其实就是panic传入的内容
		}
	}()

	empty_slice := make([]int, 0, 0)

	var res2 = max(empty_slice)

	fmt.Println(res2)

	fmt.Println("end")

}

func max(slice []int) int {

	if len(slice) == 0 || slice == nil {
		panic("数列为空")
	}

	if len(slice) == 1 {
		return slice[0]
	} else if slice[0] > max(slice[1:]) {
		return slice[0]
	} else {
		return max(slice[1:])
	}
}

defer

defer 英文原意: vi. 推迟;延期;服从 vt. 使推迟;使延期。

defer的思想类似于C++中的析构函数,不过Go语言中“析构”的不是对象,而是函数,defer就是用来添加函数结束时执行的语句。注意这里强调的是添加,而不是指定,因为不同于C++中的析构函数是静态的,Go中的defer是动态的。

defer的使用场景

简化资源的回收

典型的如文件的关闭,如以下代示例代码,打开文件后,使用defer函数延迟关闭文件,

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {

	file_name := "/Users/xinxingegeya/temp/demo.error.log"

	// read only
	inputFile, inputError := os.Open(file_name)

	if inputError != nil {
		fmt.Println("An error occurred on opening the inputfile", inputError)
	}

	defer inputFile.Close() //延迟关闭文件

	inputReader := bufio.NewReader(inputFile)

	//无条件的循环
	for {

		line, err := inputReader.ReadString('\n')

		if err == io.EOF {
			break
		}

		fmt.Println(line)
	}

}
使用 defer 函数修改函数的返回值

如下代码示例,

package main

import (
	"fmt"
)

func main() {

	res := doubleSum(1, 2)

	fmt.Println(res)
}

func doubleSum(a, b int) (sum int) {
	defer func() {
		sum *= 2
	}()
	sum = a + b
	return //可以不指定返回值,默认会返回名字为 sum 的变量
}

panic

panic 英文原意:n. 恐慌,惊慌;大恐慌 adj. 恐慌的;没有理由的 vt. 使恐慌 vi. 十分惊慌

panic 是用来表示非常严重的不可恢复的错误的。在Go语言中这是一个内置函数,接收一个interface{}类型的值(也就是任何值了)作为参数。panic的作用就像我们平常接触的异常。不过Go可没有try…catch,所以,panic一般会导致程序挂掉(除非recover)。所以,Go语言中的异常,那真的是异常了。你可以试试,调用panic看看,程序立马挂掉,然后Go运行时会打印出调用栈。 但是,关键的一点是,即使函数执行的时候panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递。所以这时候 defer 有点类似 try-catch-finally 中的 finally。 panic就是这么简单。抛出个真正意义上的异常。

recover

recover 英文原意: vt. 恢复;弥补;重新获得 vi. 恢复;胜诉;重新得球 n. 还原至预备姿势

上面说到,panic的函数并不会立刻返回,而是先defer,再返回。这时候(defer的时候),如果有办法将panic捕获到,并阻止panic传递,那就异常的处理机制就完善了。

Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了,于是,世界恢复了和平。你可以干你想干的事情了。

不过要注意的是,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回。 =========END=========

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 228
博文 577
码字总数 407134
作品 0
朝阳
程序员
Go基础编程:异常处理(error接口、panic、recover)

1 error接口 Go语言引入了一个关于错误处理的标准模式,即error接口,它是Go语言内建的接口类型,该接口的定义如下: Go语言的标准库代码包errors为用户提供如下方法: 另一个可以生成error...

tennysonsky
01/01
0
0
Golang 学习笔记(07)—— 错误及异常处理

本文为转载,原文:Golang 学习笔记(07)—— 错误及异常处理 Golang 基础知识 错误指的是可能出现问题的地方出现了问题,比如打开一个文件时失败,这种情况在人们的意料之中 ;而异常指的是...

ChainZhang
2017/12/28
0
0
Golang 异常处理机制——defer, error, panic, recover

一、前言 在实际的项目中,对于异常的最佳实践很多,在使用不同的语言开发不同类型的程序时,有不同的建议。Google C++ Style 中提到 Google 内部的 C++ 代码中不使用异常,社区也有很多关于...

吃一堑消化不良
2016/12/01
137
0
[新手学Go]Go语言的defer

defer:主要是用来处理错误。例如某个程序在运行时出现异常而下面还有事物需要处理,传统的语言遇到错误会立即终止程序活动。而go则引入了完美的容错机制——defer来处理异常错误 譬如: pack...

廖君
2013/10/27
0
0
golang捕获异常

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,...

吴之恒心
2017/03/01
0
0
golang学习的点点滴滴:异常处理 defer, panic, recover

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,...

亓斌哥哥
2014/09/29
0
0
Go的异常处理 defer, panic, recover

Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,...

blacklovebear
2014/02/09
0
0
Go圣经-学习笔记之defer和异常处理

上一篇 Go圣经-学习笔记之函数值(二) 下一篇 Go圣经-学习笔记之方法 可变参数 形参数量可变的函数称为可变参数函数。使用最多的可变参数函数标准库:。 在声明可变参数函数时,需要在参数列表...

cdh0805010
2017/10/25
0
0
[翻译] effective go 之 Errors

Errors Library routines must often return some sort of error indication to the caller. As mentioned earlier, Go's multivalue return makes it easy to return a detailed error desc......

pengfei_xue
2013/02/23
0
0
Go异常处理errors

简单用法 代码实现 执行结果 使用log.Fatalln(err)可导致程序返回状态为1,使用fmt输出则不会 自定义错误类型 代码实现 执行结果 异常捕捉 简单的异常触发和捕捉 内置函数panic发起一个异常,...

恋恋美食
02/27
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

实现异步有哪些方法

有哪些方法可以实现异步呢? 方式一:java 线程池 示例: @Test public final void test_ThreadPool() throws InterruptedException { ScheduledThreadPoolExecutor scheduledThre......

黄威
今天
0
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

六库科技
今天
0
0
牛客网刷题

1. 二维数组中的查找(难度:易) 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入...

大不了敲一辈子代码
今天
0
0
linux系统的任务计划、服务管理

linux任务计划cron 在linux下,有时候要在我们不在的时候执行一项命令,或启动一个脚本,可以使用任务计划cron功能。 任务计划要用crontab命令完成 选项: -u 指定某个用户,不加-u表示当前用...

黄昏残影
昨天
0
0
设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
昨天
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
昨天
1
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
昨天
1
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
昨天
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
昨天
1
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部