下面两个代码看起来差不多,但运行结果却天差地别
代码 1
var a int defer func() { fmt.Println(a) }() for { if a > 10 { return } a++ }
代码 2
var a int defer fmt.Println(a) for { if a > 10 { return } a++ }
结果:
代码 1 输出:11
代码 2 输出:0
![]() | 1 Asakijz 2024-07-10 22:25:32 +08:00 ![]() 可以参考下我之前提问的 t/868146#reply11 |
2 SimbaPeng 2024-07-10 22:31:08 +08:00 a 的求值时间 |
3 sduoduo233 2024-07-10 22:36:25 +08:00 via Android defer 的参数会提前求值 A defer statement defers the execution of a function until the surrounding function returns. The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns. |
4 dilu 2024-07-10 22:38:21 +08:00 via Android 斗胆分析一下,第一种写法明显是在 func 结构体引用了一个外部变量,典型的闭包问题。而第二种写法的 defer 只是一个表达式,编译后只是一个简单的 funval 而没有对应的捕获列表。第一种写法在主函数执行完开始执行 defer 函数的时候,加载了这个 func 的 funcval 和捕获列表,其中对于 a 的引用是地址的形式,此时 a 是 10 故而打印了 10 。 |
5 extrem 2024-07-10 23:23:15 +08:00 defer 语句将函数的执行推迟到周围的函数返回。 延迟调用的参数会立即计算,但在周围的函数返回之前不会执行函数调用。 |
6 dobelee 2024-07-10 23:30:45 +08:00 存在传入局部变量时都用匿名函数。 一般只有简单的关闭操作才会直接写表达式,比如 defer x.Close() defer cancel() |
8 0x90200 2024-07-11 09:27:54 +08:00 |
![]() | 9 supuwoerc 2024-07-11 14:16:45 +08:00 这是一个闭包吧~ |
![]() | 10 supuwoerc 2024-07-11 14:24:55 +08:00 找了一下我当初写的 Demo: ```go package main import "fmt" func main() { Demo1() fmt.Println("----------") Demo2() fmt.Println("----------") Demo3() } func Demo1() { for i := 0; i < 3; i++ { defer func() { fmt.Println(i) // 每次循环的 i 都是同一个 i(demo1 函数作用域中的 i ,这个上下文中的 i 在函数执行前 i 已经自增加到 3) }() } } func Demo2() { for i := 0; i < 3; i++ { defer func(val int) { fmt.Println(val) // 函数声明时的参数,并未产生闭包,正常执行 }(i) } } func Demo3() { for i := 0; i < 3; i++ { k := i // 每次循环产生一个新的 k ,函数引用这个上下文中的 k ,后续的循环并不会修改每个上下文中的 k defer func() { fmt.Println(k) }() } } ``` |
11 wanminny 2024-07-11 17:39:08 +08:00 defer 语句将函数的执行推迟到周围的函数返回。 延迟调用的参数会立即计算,但在周围的函数返回之前不会执行函数调用。 |
![]() | 12 wswch4444 2024-07-11 17:39:25 +08:00 关键区别就在 defer func() { fmt.Println(a) }() defer fmt.Println(a) 一个用了闭包,一个没用,没有用的,是在 编译到这个 defer 语句就确定了 a 的数值 零值 0 用了闭包 是在 函数执行完 之后 给 a 赋值 所以是 11 |
13 dyllen 2024-07-20 10:42:08 +08:00 defer 相当于把一个函数放到栈里面稍后执行,函数参数会先计算好结果再放入栈。 |