温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

go defer的作用是什么

发布时间:2021-07-10 11:35:32 阅读:285 作者:chen 栏目:编程语言
GO开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍“go defer的作用是什么”,在日常操作中,相信很多人在go defer的作用是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”go defer的作用是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

 

defer 关键字

很多现代的编程语言中都有 defer 关键字,Go 语言的 defer 会在当前函数返回前执行传入的函数,它会经常被用于关闭文件描述符、关闭数据库连接以及解锁资源。

使用 defer 的最常见场景是在函数调用结束后完成一些收尾工作,例如在 defer 中回滚数据库的事务:

func InsertObj() error {    //获取一个数据库session    db := db.GetDB().Begin()    defer db.Rollback()        //do someting    err := db.Insert()        if err != nil{     return err    }        return db.Commit().Error}
 

在使用数据库事务时,我们可以使用上面的代码在创建事务后就立刻调用 Rollback 保证事务一定会回滚。哪怕事务真的执行成功了,那么调用 Commit() 之后再执行 Rollback() 也不会影响已经提交的事务。

 

defer的特性

  • defer 的调用时机以及多次调用     defer 时执行顺序
  • defer 使用传值的方式传递参数时会进行预计算,导致不符合预期的结果
func main() {	defer fmt.Println(0)        defer fmt.Println(1)        defer fmt.Println(2)        defer fmt.Println(3)        	}
 

上面的代码输出:

3210
 

那么defer的执行顺序就是先进后出

func main() {    {        defer fmt.Println("defer runs")        fmt.Println("block ends")    }        fmt.Println("main ends")}
 

输出:

block endsmain endsdefer runs
 

可以看出defer不是在退出代码块的作用域时执行的,它只会在当前函数和方法返回之前被调用

 

预计算

func main() {	startedAt := time.Now()	defer fmt.Println(time.Since(startedAt))	time.Sleep(time.Second)}
 

输出:

0s
 

调用 defer 关键字会立刻拷贝函数中引用的外部参数,所以 time.Since(startedAt) 的结果不是在 main 函数退出之前计算的,而是在 defer 关键字调用时计算的,最终导致上述代码输出 0s。

那么如果要解决这个问题可以改写代码

func main() {	startedAt := time.Now()	defer func() { fmt.Println(time.Since(startedAt)) }()	time.Sleep(time.Second)}
 

输出:

1s
 

虽然调用 defer 关键字时也使用值传递,但是因为拷贝的是函数指针

 

defer 常用的案例

捕获异常和崩溃日志:

func process() error {	defer func() {                //防止意外之外的错误导致程序崩溃		if err := recover(); err != nil {                        //崩溃日志的捕获			core.LogPnc.Errorf("panic : %v", err)			core.LogPnc.Errorf("%s", string(debug.Stack()))		}	}()        //do something	err := obj.CALL(parseYML)	if err != nil {		return err	}	return nil}
 

释放锁:

func runTask() {        //上锁	c.lk.Lock()        //释放锁	defer c.lk.Unlock()	//do something}
 

在函数返回之前进行业务操作

func (c *ProcessEngine) Process(ph *ProcessHook) {	defer func() {		c.lk.Lock()                //逻辑处理		c.running--		c.lk.Unlock()	}()        //do something}

到此,关于“go defer的作用是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/superhreojim/blog/5018851

go
AI

开发者交流群×