xdm , 不知道你们是否有使用过 defer ,这种语法在是 go 特有的,用起来真是爽的不要不要的
很多时候,我们在使用一些新东西,出现一些莫名其妙的现象或者是结果的时候,我们总会认为,这个东西不友好, 这个东西好坑,好奇怪
其实我们是要弄明白其中的注意点,原理,当出现所谓的奇怪现象的时候,处理起来就会得心应手得多
xdm,这里准备了如下注意事项,请查收
案例 1
这里先统一说明一下 defer 是干什么的?
是 GO 中的一个关键字
这个关键字,我们一般用在释放资源,在 return
前会调用他
如果程序中有多个 defer
,defer 的调用顺序是按照类似栈的方式,后进先出 LIFO
的 , 具体的 defer 实现原理可以查看我的历史文章 GO 中 defer的实现原理
先来看一个 demo,猜一猜他的输出是什么?
写一个 defer 和 defer 在一起的 输入输出顺序 demo
- 简单写 4 个函数,分别应用到 defer 上
func test1() { fmt.Println("test 1") } func test2() { fmt.Println("test 2") } func test3() { fmt.Println("test 3") } func test4() { fmt.Println("test 4") } func main() { defer test1() defer test2() defer test3() defer test4() }
运行上述代码,我们期望的结果是什么呢?
test 1 test 2 test 3 test 4
还是
test 4 test 3 test 2 test 1
小伙伴们感兴趣的可以运行一下,结果是 第二种,defer 我们可以理解为是一个入栈操作,先进后出
入栈 : test1(),test2(),test3(),test4()
出栈 : test4(),test3(),test2(),test1()
案例 2
上面我们知道 defer 和 defer 的顺序是按照栈的顺序来,那么我们下面来看看 defer 和 return 的顺序又是什么样子的 ?
- 简单写 一个用于 return 的函数和 用于 defer 的函数
func testDefer() { fmt.Println("testDefer") } func testReturn() int { fmt.Println("testReturn") return 1 } func myTest() int { defer testDefer() return testReturn() } func main() { myTest() }
再来猜测一下上述编码会是如何执行的呢
是这样的吗?
testDefer testReturn
还是这样的 ?
testReturn testDefer
结果仍然是第二种,通过上述编码我们可以看出来 defer 后面的语句 是晚执行的, return 后面的语句是先执行的
那么如果是 多个 defer 和 return 放在一起呢?
xdm ,咱们举一反三了,那肯定还是 return 先执行,defer 按照栈的顺序执行
案例 3
这个案例咱们加上简单的计算,看看效果如何
- 简单些一下带有计算的 defer
func testDefer(num int)(res int){ defer func(){ res = num + 3 }() return num } func main(){ res := testDefer(5) fmt.Println(res) }
上述编码运行后会是什么效果呢
是 5 吗? 是 8 吗?反正肯定不是 3 吧
思考一下,按照上面案例 1 的逻辑,结果是 8
老铁,没毛病, num 通过 testDefer 函数传值,赋值 为 5 ,return num
的时候,返回值是 5,再执行 defer 语句, 5+3 就是 8
好了,今天就到这里,感兴趣的朋友也可以玩起来
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~