Непонятно, что происходит с отложенной обработкой ошибок и отложенным восстановлением в процессе работы

Меня смущает ключевое слово defer, пока я изучаю golang

  1. отложить обработку ошибок
package main

import (
    "errors"
    "fmt"
)

func handleErr(err error) {
    fmt.Println(err)
}

func returnErr() (err error) {
    defer handleErr(err)

    return errors.New("boo")
}

func main() {
    returnErr()
}

почему результат равен нулю?

  1. отложить восстановление
package main

func raisePanic() {
    defer recover()

    panic("boo")
}

func main() {
    raisePanic()
}

почему все еще паника?

Большое спасибо.

Во второй части на этот вопрос есть ответ.

Timsib Adnap 31.08.2024 05:58
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
1
1
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оба ваших вопроса вызваны одной и той же причиной, давайте объясним это с точки зрения исходного кода. Ключевая часть кода находится в normalizeGoDeferCall . Как описано в комментарии

normalizeGoDeferCall нормализует вызов в обычный вызов функции без аргументов и результатов, подходит для использования в OGO/ODEFER заявление. Когда компилятор анализирует ключевое слово go/defer, выражение вызова с аргументами после них будет анализироваться как функция без аргументов, следовательно

defer f(x, y)

будет преобразован в

x1, y1 := x, y
defer func() { f(x1, y1) }()

Вернуться к вашим вопросам

  1. отложить обработку ошибок
defer handleErr(err)

будет преобразован в

err1 := err
defer func() { handleErr(err1) }()

err оценивается, сохраняется заново и передается в handleErr, так всегда будет nil

Правильный способ сделать это:

defer func() {handleErr(err)}()
  1. отложить восстановление у восстановления вроде нет аргументов, но оно связано с реальной реализацией gorecover, чтобы оно было преобразовано в
argp := getcallersp()
defer func(){
    gorecover(argp)
}()
    if p != nil && !p.goexit && !p.recovered && argp == uintptr(p.argp) {
        p.recovered = true
        return p.arg
    }

Его можно восстановить, если два argp равны, но, очевидно, это не так. Если мы изменим это следующим образом:

func raisePanic() {
    defer func() {
        recover()
    }()

    panic("boo")
}

argp — это функция, зарегистрированная путем вызова defer после того, как в этом случае произойдет panic. Эта функция вызывается gopanic. Следовательно, argp — это sp функции gopanic. Он рассчитывается и передается в gorecover. После сравнения gorecover считает argp равным p.argp, поэтому его можно восстановить.

Другие вопросы по теме