Я экспериментирую с 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, это выводит:
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)
не будет вызываться до тех пор, пока основная функция не вернется. .
Однако это не объясняет, почему в первом примере increaseZ(10)
выводится до завершения main, а во втором примере - после завершения main.
Я был бы признателен, если бы кто-нибудь мог помочь мне понять, что здесь происходит, поскольку это выглядит как благодатная почва для трудных для диагностики ошибок в дальнейшем.
println
наfmt.Println
, чтобы получить ожидаемый результат. - person Cerise Limón   schedule 28.03.2015println
. Из документации: […] в зависимости от реализации […] не гарантируется, что язык останется на языке. - person Dave C   schedule 28.03.2015