V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
EileenJ
V2EX  ›  Go 编程语言

问一个 go 延迟调用的问题

  •  
  •   EileenJ · 2019-06-10 21:32:15 +08:00 · 3042 次点击
    这是一个创建于 1996 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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

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

    11 条回复    2019-06-13 12:38:12 +08:00
    zyqzyq08
        1
    zyqzyq08  
       2019-06-10 21:39:07 +08:00 via Android   ❤️ 1
    闭包问题
    gamexg
        2
    gamexg  
       2019-06-10 21:43:11 +08:00
    在循环结束时 defer 才会执行,
    第一个输出的是 for 语句的 i 的值,这时候 i 已经是 3 了( (3<3)!=true,循环结束 )。

    第二个输出的是局部变量 i,当然是 2、1、0.
    chy373180
        4
    chy373180  
       2019-06-10 22:09:30 +08:00
    @chy373180 不过我有个疑问,如何理解第二个回答中的例子
    liulaomo
        5
    liulaomo  
       2019-06-10 23:36:35 +08:00
    两个关键点:
    1. 所有循环步共享同一个循环变量 i
    2. 延迟调用在循环之后(程序退出之前)执行
    liulaomo
        6
    liulaomo  
       2019-06-10 23:37:53 +08:00
    第二个例子中的左 i 和右 i (循环变量)不同,每个循环步有自己独立的左 i
    j2gg0s
        7
    j2gg0s  
       2019-06-10 23:38:15 +08:00
    第一个只有一个变量;第二个有四个变量
    hduwillsky
        8
    hduwillsky  
       2019-06-11 07:06:32 +08:00 via iPhone
    闭包是引用传值
    zhyl
        9
    zhyl  
       2019-06-11 08:41:10 +08:00 via Android
    第二个循环中每次都会定义 i,闭包中引用的是每次新定义的 i 的值,依次是 0 1 2,defer 先入后出打印出来就是 2 1 0
    beidounanxizi
        10
    beidounanxizi  
       2019-06-13 12:36:41 +08:00 via iPhone
    闭包传值问题。go 是按值传递,参见 https://github.com/golang/go/wiki/CommonMistakes
    beidounanxizi
        11
    beidounanxizi  
       2019-06-13 12:38:12 +08:00 via iPhone
    @hduwillsky go 只有按值传递,没有引用传值,有值类型和引用类型,楼主的问题是 loop goroutime 的执行问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4583 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:10 · PVG 18:10 · LAX 02:10 · JFK 05:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.