четверг, 30 апреля 2020 г.

Отложить вызов функции (с возвращаемым значением) в Golang

Оператор defer откладывает выполнение функции до тех пор, пока не вернется окружающая функция, либо в обычном режиме, либо через panic.

func main() {
    defer fmt.Println("World")
    fmt.Println("Hello")
}

Вывод:

Hello
World

Отложенные вызовы выполняются даже при панике функции:

func main() {
    defer fmt.Println("World")
    panic("Stop")
    fmt.Println("Hello")
}

Вывод:

World
panic: Stop

goroutine 1 [running]:
main.main()
    ../main.go:3 +0xa0

Порядок исполнения

Аргументы отложенного вызова вычисляются немедленно, даже если вызов функции не выполняется до тех пор, пока не вернется окружающая функция.

Если имеется несколько отложенных вызовов функций, они выполняются в порядке "последний пришел - первым вышел".

func main() {
    fmt.Println("Hello")
    for i := 1; i <= 3; i++ {
        defer fmt.Println(i)
    }
    fmt.Println("World")
}

Вывод:

Hello
World
3
2
1

Используйте func для возврата значения

Отложенные анонимные функции могут получать доступ и изменять именованные возвращаемые параметры окружающей функции.

В этом примере функция foo возвращает "Change World".

func foo() (result string) {
    defer func() {
        // изменяет значение в самый последний момент
        result = "Change World" 
    }()
    return "Hello World"
}

Применение defer

Defer часто используется для выполнения действий по очистке, таких как закрытие файла или разблокировка мьютекса. Такие действия должны выполняться как в случаях когда функция возвращается нормально, так и когда она паникует.

Закрытие файла

В этом примере операторы defer используются для того, чтобы все файлы были закрыты перед выходом из функции CopyFile, в зависимости от того, как это происходит.

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()

    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    defer dst.Close()

    return io.Copy(dst, src)
}

Обработка ошибок: поймать panic

Defer также может быть использован для восстановления (recover) после panic и обновления возвращаемого значения.


Читайте также:


Комментариев нет:

Отправить комментарий