Go - 延迟函数的不一致评估

我正在尝试使用 Go 并且看到一些带有延迟函数的意外行为。考虑以下将全局变量增加给定数量的程序。


package main


import "fmt"


var z = 1


func main() {


    defer increaseZ(10)

    defer fmt.Println("z =", increaseZ(20), "Deferred Value 1")

    defer fmt.Println("z =", increaseZ(30), "Deferred Value 2")


    fmt.Println("z =", z, "Main Value")

}


func increaseZ(y int) int {

    z += y

    println("z =", z, "Inside Increase Function")

    return z

}

当在 go playground 中运行时,输出:


z = 21 Inside Increase Function

z = 51 Inside Increase Function

z = 61 Inside Increase Function

z = 51 Main Value

z = 51 Deferred Value 2

z = 21 Deferred Value 1

如果我切换延迟函数的顺序,它还有另一个效果:


defer fmt.Println("z =", increaseZ(20), "Deferred Value 1")

defer fmt.Println("z =", increaseZ(30), "Deferred Value 2")

defer increaseZ(10)

输出:


z = 21 Inside Increase Function

z = 51 Inside Increase Function

z = 51 Main Value

z = 61 Inside Increase Function

z = 51 Deferred Value 2

z = 21 Deferred Value 1

Go 文档指出:


延迟调用的参数会立即计算,但直到周围的函数返回时才会执行函数调用。


因此,正在评估的参数可以解释为什么返回的 Main Value 是 51 而不是 61,因为 fmt.Println 语句将increaseZ作为参数,但defer increaseZ(10)在 main 函数返回之前不会被调用。


但是,这并不能解释为什么在第一个示例中increaseZ(10)在 main 完成之前输出,而在第二个示例中在 main 完成之后输出。


如果有人能帮助我了解这里发生的事情,我将不胜感激,因为这看起来像是难以诊断错误的沃土。


慕村225694
浏览 241回答 3
3回答

BIG阳

您的打印目的地不一致。stdout: fmt.Printlnstderr: println写入相同的打印目的地。package mainimport "fmt"var z = 1func main() {    defer increaseZ(10)    defer fmt.Println("z =", increaseZ(20), "Deferred Value 1")    defer fmt.Println("z =", increaseZ(30), "Deferred Value 2")    fmt.Println("z =", z, "Main Value")}func increaseZ(y int) int {    z += y    fmt.Println("z =", z, "Inside Increase Function")    return z}输出:z = 21 Inside Increase Functionz = 51 Inside Increase Functionz = 51 Main Valuez = 51 Deferred Value 2z = 21 Deferred Value 1z = 61 Inside Increase Function或者,package mainimport (    "fmt"    "os")var z = 1func main() {    defer increaseZ(10)    defer fmt.Fprintln(os.Stderr, "z =", increaseZ(20), "Deferred Value 1")    defer fmt.Fprintln(os.Stderr, "z =", increaseZ(30), "Deferred Value 2")    fmt.Fprintln(os.Stderr, "z =", z, "Main Value")}func increaseZ(y int) int {    z += y    println("z =", z, "Inside Increase Function")    return z}输出:z = 21 Inside Increase Functionz = 51 Inside Increase Functionz = 51 Main Valuez = 51 Deferred Value 2z = 21 Deferred Value 1z = 61 Inside Increase Function

红糖糍粑

我怀疑这是 Go 游乐场的错误。当我在我的机器上编译并运行这个程序时,它会产生预期的输出。一个bug报告关于这个问题已经提交。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go