我正在尝试使用 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.
所以正在评估的参数,可以解释为什么返回的主值是 51 而不是 61,因为 fmt.Println 语句将 increaseZ
作为参数,但是 defer increaseZ(10)
直到主函数返回后才会被调用。
但是,这并不能解释为什么在第一个示例中 increaseZ(10)
在 main 完成之前输出,而在第二个示例中在 main 完成之后输出。
如果有人能帮助我理解这里发生的事情,我将不胜感激,因为这看起来像是为进一步诊断难以诊断的错误提供了沃土。
最佳答案
您的打印目的地不一致。
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 - 延迟函数的不一致评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29316958/