V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ArianX

关于 Go defer 对匿名返回值和命名返回值的不同行为

  •  
  •   ArianX ·
    arianxx · May 14, 2019 · 4519 views
    This topic created in 2541 days ago, the information mentioned may be changed or developed.
    func test1() int {
    	var a int
    
    	defer func() {
    		a++
    	}()
    
    	return a
    }
    
    func test2() (a int) {
    	defer func() {
    		a++
    	}()
    
    	return a
    }
    

    test1 最终返回 0,test2 最终返回 1

    这种令人混淆的行为是一个语言缺陷还是一个 feature ?

    今天面试碰上没答起,潜意识认为这两货没区别😥

    reus
        1
    reus  
       May 14, 2019
    说明你不知道 defer 是在什么时机执行的,基础不牢。
    面试就是要试出你的真实水平,有人连 abc 都认不全,难道是字母“令人混淆”?难道是字母有“缺陷”?
    ArianX
        2
    ArianX  
    OP
       May 14, 2019
    @reus #1 好的,golang 设计出这两种差异的意愿是因为要说明我基础不牢固
    FEDT
        3
    FEDT  
       May 14, 2019 via iPhone
    有答案吗
    zzn
        4
    zzn  
       May 14, 2019
    似乎并不怎么令人混淆吧?
    blless
        5
    blless  
       May 14, 2019 via Android
    你这代码有问题吧
    silenceshell
        6
    silenceshell  
       May 14, 2019   ❤️ 1
    defer 发生在“真正”的 retrun 之前。
    Maboroshii
        7
    Maboroshii  
       May 14, 2019
    学习了。顺便翻了一下资料
    https://blog.golang.org/defer-panic-and-recover
    > 3.Deferred functions may read and assign to the returning function's named return values.
    ArianX
        8
    ArianX  
    OP
       May 14, 2019 via Android
    @silenceshell 这是作用机制层面上的吧。我想讨论的是究竟为什么要这样设计,在什么场景会用到
    Zzdex
        9
    Zzdex  
       May 14, 2019
    @ArianX #8 你看楼上的链接,This is convenient for modifying the error return value of a function;
    便于修改错误的返回值
    victor
        10
    victor  
       May 15, 2019   ❤️ 1
    ArianX
        11
    ArianX  
    OP
       May 15, 2019 via Android
    匿名返回值函数里的 defer 也能访问到返回值,也允许写出修改返回值的语句,为什么要设计为修改对最终返回的值无效?为什么不直接设计为不允许修改?利用到这种差异的场景是什么?
    poplar50
        12
    poplar50  
       May 15, 2019 via Android
    学习了,七楼发的链接我看 go tour 的时候还翻过,但是竟然没注意这个。现在想想,defer 既然被设计用来做一些收尾工作,那么出现这种情况就是为了让 defer 也能够处理函数返回值吧。
    ArianX
        13
    ArianX  
    OP
       May 15, 2019 via Android
    好吧,突然想到某些场景下可能不需要修改最终返回值,但需要在 defer 里使用返回的值做一些操作,于是允许匿名返回值里的 defer 修改返回值,就能够复用同一个变量。
    ArianX
        14
    ArianX  
    OP
       May 15, 2019 via Android
    话说我想讨论的是为什么要特别设计出匿名返回值和命名返回值 defer 行为的差异,而不是在 defer 里修改返回值的意图
    catror
        15
    catror  
       May 15, 2019 via Android   ❤️ 1
    你可以这么理解,返回值其实是关联有一个返回变量的,第一个例子里,因为匿名,defer 函数访问不到返回变量,而变量 a 只是局部变量,修改局部变量自然是影响不到返回变量。
    nuance2ex
        16
    nuance2ex  
       May 15, 2019 via iPhone   ❤️ 1
    @ArianX

    10 楼,这篇从底层原理说了,刚看了不错。
    gamexg
        17
    gamexg  
       May 15, 2019 via Android
    如 @catror 所说可以认为返回值也是一个变量。
    test1 里面修改的只是局部变量,并未修改 return 变量。
    test2 才是修改的 return 变量。

    可以返回结构指针试试,和不同变量一样,test1 修改结构成员也会修改返回值了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1136 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 73ms · UTC 18:14 · PVG 02:14 · LAX 11:14 · JFK 14:14
    ♥ Do have faith in what you're doing.