Go: вы должны знать это, прежде чем использовать Defer
Defer - одна из моих любимых вещей в Go. Вы можете использовать его, чтобы убедиться, что операция выполняется до возврата из функции. Это очень полезно. Я думаю, что почти все программисты Go, если не все, использовали оператор defer
в своих приложениях. Но есть одна вещь, которую вы должны знать, прежде чем использовать defer в Go.
Итак, что вы должны знать перед использованием defer? Дело в том, что параметр отложенной функции оценивается немедленно, даже если функция выполняется до возврата из содержащей ее функции. Это написано в спецификации и в Tour of Go, но я думаю, что некоторые из тех, кто его использует, сначала не знали об этом (включая меня, ха-ха). Так что это значит? Посмотрим на это в действии.
Я использую этот код, чтобы попробовать:
func myFunc() {
myStr := "intial"
defer deferedFunc(myStr)
myStr = "altered"
fmt.Println("myFunc's myStr: ", myStr)
}
func deferedFunc(str string) {
fmt.Println("deferedFunc's str: ", str)
}
Есть две функции, myFunc
и deferedFunc
. myFunc
объявляет и инициует переменную строки, а затем использует Defer со строкой в качестве параметра deferedFunc
, и далее изменяет значение строки и далее выводить строку. deferedFunc
напечатает данный параметр.
Запустите код, и я получил в терминале:
myFunc's myStr: altered
deferedFunc's str: intial
Вы видите, что fmt.Println
в deferedFunc
выполняется последним, но у него есть параметр начального строкового значения. Значение строки изменяется перед вызовом отложенной функции, но отложенная функция получила начальное значение, потому что оно вычисляется немедленно, когда используется defer.
Так что, если мы хотим передать последнее значение методу deferedFunc
? Для этого мы можем отложить анонимную функцию, которая вызывает deferedFunc
.
func myFunc() {
myStr := "intial"
defer func() {
deferedFunc(myStr)
}()
myStr = "altered"
fmt.Println("myFunc's myStr: ", myStr)
}
func deferedFunc(str string) {
fmt.Println("deferedFunc's str: ", str)
}
В этом случае мы получим:
myFunc's myStr: altered
deferedFunc's str: altered
Я думаю, это важно знать, потому что вы можете избежать неожиданных ошибок при использовании defer. Вы также можете поделиться этой информацией с другими, чтобы ваши коллеги не допустили неожиданных ошибок.