Panic, recover в golang

Несмотря на наличие мануала непросто досконально понять, как работают конструкции panic и recover.

Наиболее понятная из двух функций — panic, она работает идентично выбрасыванию исключения: прерывает выполнение программы, собирает в свой стек все вызовы ф-ций, которые привели к директиве panic, вся эта информация будет выведена в консоль.

Обработать panic может помочь ф-ция recover. Ф-ция сама по себе бессмысленна и использоваться должна в следующем фрагменте кода:
defer func() {
    if r := recover(); r != nil {
        // любые действия при возникновении ошибки
    }
}()


Как видим recover вызывается внутри отложенной (defer) конструкции.
Код defer вызывается при завершении ф-ции, в которой он описан. При чем вызовется он в любом случае: в случае рядового завершения ф-ции; при панике паники; в случае завершения всей программы после SIGKILL.

Recover похож на catch, но всё же не дотягивает до него, т.к. после catch можно продолжить выполнение ф-ции как угодно, например вернуть какое-то другое значение (вызвать return). Recover же даёт возможность выполнить некоторое действие, но повлиять на возвращаемое ф-цией значение уже не может, т.к. он выполняется recover в контексте defer.

Интересно, что ф-ция, внутри которой сработал defer-recover, вернёт дефолтное значение своего типа. Например, если ф-ция bool, то false. Если int, то 0. Если указатель, то nil.

Пример ниже показывает то, что ф-ция типа *string после recover вернёт nil, как бы не хотелось получить указатель на 456.
s:= func() *string {
    defer func() {
        if r := recover(); r != nil {
            d := "456"
            return &d
        }
    }()
    panic("error");
    d := "123"
    return &d
}()

log.Printf("%+v\n", s) // выведет nil