问一个 go 延迟调用的问题

2019-06-10 21:32:15 +08:00
 EileenJ
package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		defer func() {
			fmt.Println("a:", i)
		}()
	}
}

输出是:
a:3
a:3
a:3


package main

import "fmt"

func main() {
	for i := 0; i < 3; i++ {
		i := i
		defer func() {
			fmt.Println("a:", i)
		}()
	}
}

输出是:
a:2
a:1
a:0

为什么两个的运行结果会不一样呢?

2919 次点击
所在节点    Go 编程语言
11 条回复
zyqzyq08
2019-06-10 21:39:07 +08:00
闭包问题
gamexg
2019-06-10 21:43:11 +08:00
在循环结束时 defer 才会执行,
第一个输出的是 for 语句的 i 的值,这时候 i 已经是 3 了( (3<3)!=true,循环结束 )。

第二个输出的是局部变量 i,当然是 2、1、0.
chy373180
2019-06-10 21:52:34 +08:00
chy373180
2019-06-10 22:09:30 +08:00
@chy373180 不过我有个疑问,如何理解第二个回答中的例子
liulaomo
2019-06-10 23:36:35 +08:00
两个关键点:
1. 所有循环步共享同一个循环变量 i
2. 延迟调用在循环之后(程序退出之前)执行
liulaomo
2019-06-10 23:37:53 +08:00
第二个例子中的左 i 和右 i (循环变量)不同,每个循环步有自己独立的左 i
j2gg0s
2019-06-10 23:38:15 +08:00
第一个只有一个变量;第二个有四个变量
hduwillsky
2019-06-11 07:06:32 +08:00
闭包是引用传值
zhyl
2019-06-11 08:41:10 +08:00
第二个循环中每次都会定义 i,闭包中引用的是每次新定义的 i 的值,依次是 0 1 2,defer 先入后出打印出来就是 2 1 0
beidounanxizi
2019-06-13 12:36:41 +08:00
闭包传值问题。go 是按值传递,参见 https://github.com/golang/go/wiki/CommonMistakes
beidounanxizi
2019-06-13 12:38:12 +08:00
@hduwillsky go 只有按值传递,没有引用传值,有值类型和引用类型,楼主的问题是 loop goroutime 的执行问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/572613

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX