Go-延迟函数的不一致求值
我正在试验Go,并看到一些延迟函数的意外行为。考虑下面的程序,将给定变量的全局变量递增。Go-延迟函数的不一致求值,go,deferred-execution,Go,Deferred Execution,我正在试验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")
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
}
当出现以下情况时,将输出:
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文档说明:
将立即计算延迟调用的参数,但
函数调用在周围函数返回之前不会执行
因此,正在求值的参数可能会解释为什么返回的主值是51而不是61,因为fmt.Println语句将increaseZ
作为参数,但是defer increaseZ(10)
直到主函数返回后才会被调用
然而,这并不能解释为什么在第一个示例中,increaseZ(10)
在main完成之前输出,在第二个示例中在main完成之后输出
如果有人能帮助我了解这里发生了什么,我将不胜感激,因为这里似乎是难以诊断的细菌的沃土。我怀疑这是Go游乐场的细菌。当我在我的机器上编译并运行这个程序时,它会产生预期的输出。这个问题的相关文件已经提交。我怀疑这是Go游乐场的一个bug。当我在我的机器上编译并运行这个程序时,它会产生预期的输出。此问题已提交相关文件。您的打印目的地不一致
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
}
写入相同的打印目标
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
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
或者
输出:
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
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
您的打印目标不一致
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
}
写入相同的打印目标
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
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
或者
输出:
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
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
这不是延迟评估的问题。是关于印刷的
println
函数的完整性有文档记录,但不保证使用该语言。此外,通过设计,Stdout和Stderr在操场上合二为一。
如果您在任何地方都使用fmt.Println(…)
或者明确定义
fmt.Fprintln(os.Stdout,
事情会按预期进行。这不是关于延迟的评估。这是关于打印。println
函数记录完整,但不保证保留在语言中。此外,Stdout和Stderr通过设计在操场上合并为一个流。
如果您在任何地方都使用fmt.Println(…)
或者显式定义
fmt.Fprintln(os.Stdout,
事情会按预期进行。这很有趣。游乐场不会交错Stdout和stderr。请参阅。将println
更改为fmt.println
以获得预期的输出。不要以特定于实现的方式使用“[…]这很有趣。游乐场不会交错使用stdout和stderr。请参阅。将println
更改为fmt.println
,以获得预期的输出。不要以特定于实现的方式使用“[…]它不一定会保留在该语言中。”经过验证,在go1.4.2 darwin/amd64上编译时,它按预期运行。注意:已被拒绝为无效。没有Go错误。行为如预期。错误在程序中。有关详细信息,请参阅我的答案。它未被拒绝,我关闭了它。奇怪的是,我无法通过任何其他方式重现此行为。Vali日期为,在go1.4.2 darwin/amd64上编译时,它按预期运行。注意:已被拒绝为无效。没有Go错误。行为如预期。错误在程序中。有关详细信息,请参阅我的答案。它未被拒绝,我关闭了它。奇怪的是,我无法通过任何其他方式重现此行为。println
writing tostderr
完美地解释了这一点。你能分享一下这一点吗?@PassKit:在Go伪包文档中。println
内置函数以特定于实现的方式格式化其参数,并将结果写入标准错误。println
writing tostderr
解释得很好。你能分享一下这是在哪里记录的吗?@PassKit:在Go伪包文档中:println
内置函数以特定于实现的方式格式化其参数,并将结果写入标准错误。