DevGang
Авторизоваться

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. Вы также можете поделиться этой информацией с другими, чтобы ваши коллеги не допустили неожиданных ошибок.

Источник:

#Golang
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

Поделитесь своим опытом, расскажите о новом инструменте, библиотеке или фреймворке. Для этого не обязательно становится постоянным автором.

Попробовать

В подарок 100$ на счет при регистрации

Получить