当前位置: 首页 > 后端技术 > PHP

Go群友问:学习defer的时候很迷茫,但是我做不到这个!

时间:2023-03-29 20:35:18 PHP

有任何问题或建议,请及时交流碰撞。我的公众号是【脑补成炸鱼】,GitHub地址:https://github.com/eddycjy。大家好,我是炸鱼。前几天在读者交流群里看到一个小伙伴,向大家请教Go相关的技术问题。问题是:“各位,我在学习defer的时候遇到闭包很迷茫,谁理解的比较清楚,能指点一下吗?”他的问题是Go语言中的以下延迟主题。让我们看一下:funcmain(){varwhatever[6]struct{}fori:=rangewhatever{deferfunc(){fmt.Println(i)}()}}请思考输出答案是什么。按照自己的理解,这位小伙伴认为应该输出xx。但是最后的输出可能和他想的有出入,他一时间也想不通。这个程序的输出是:为什么555555都是5,为什么不是0、1、2、3、4、5?根本原因是关闭。原因有二:for循环结束后,局部变量i的值已经是5了,defer的闭包直接引用了变量i。结合defer关键字的特点,可以知道它会在main方法体结束后执行。综合以上,最终输出的结果是递增后的5。进一步思考现在我们明白了原因,让我们再次转换它。再看另一种情况,代码如下:funcmain(){varwhatever[6]struct{}fori:=rangewhatever{deferfunc(iint){fmt.Println(i)}(i)}}与第一种情况不同,这次我们传入了变量i。那么他的输出是什么呢?这个程序的输出是:为什么543210是5,4,3,2,1,0,为什么不是0,1,2,3,4,5?(炸鱼是不是打错了?)根本原因在于两点:在for循环中,局部变量i已经传入了deferfunc,属于值传递。它的值是在声明defer语句时确定的。结合defer关键字的特点,按照先进后出的顺序执行。综合以上,最终输出为5,4,3,2,1,0。下一题没多久,这位小伙伴又有了新的领悟。抛出一个新的示例问题,如下:funcf1()(rint){deferfunc(){r++}()return0}funcf2()(rint){t:=5deferfunc(){t=t+5}()returnt}funcf3()(rint){deferfunc(rint){r=r+5}(r)return1}主要函数:funcmain(){println(f1())println(f2())println(f3())}请思考输出的答案是什么。这个程序的输出是:为什么151是1、5、1而不是0、10、5或其他答案?欢迎大家在下方评论区留言讨论,分享解决问题的思路,共同思考,共同进步。我的公众号分享Go语言、微服务架构和奇怪的系统设计。欢迎关注我的公众号与我交流交流。最好的关系是相互成就。您的喜欢是创作炸鱼最大的动力。感谢您的支持。