OGeek|极客世界-中国程序员成长平台

标题: go - Go-延迟函数的不一致评估 [打印本页]

作者: 菜鸟教程小白    时间: 2022-8-16 02:59
标题: go - 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
}

run in the 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文档指出:

The deferred call's arguments are evaluated immediately, but the function call is not executed until the surrounding function returns.



因此,正在评估的参数可以解释为什么返回的Main Value是51而不是61,因为fmt.Println语句将increaseZ作为参数,但是直到主函数返回后才调用defer increaseZ(10)

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

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



Best Answer-推荐答案


您的打印目的地不一致。

stdout: fmt.Println

stderr: println

写入相同的打印目的地。
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
    fmt.Println("z =", z, "Inside Increase Function")
    return z
}

输出:
z = 21 Inside Increase Function
z = 51 Inside Increase Function
z = 51 Main Value
z = 51 Deferred Value 2
z = 21 Deferred Value 1
z = 61 Inside Increase Function

或者,
package main

import (
    "fmt"
    "os"
)

var z = 1

func 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 Function
z = 51 Inside Increase Function
z = 51 Main Value
z = 51 Deferred Value 2
z = 21 Deferred Value 1
z = 61 Inside Increase Function

关于go - Go-延迟函数的不一致评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29316958/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (https://www.ogeek.cn/) Powered by Discuz! X3.4