встроенная ошибка нулевого указателя - PullRequest
0 голосов
/ 12 мая 2018

Почему я получаю ошибку нулевого указателя при попытке напечатать указатель с неинициализированной встроенной ошибкой:

package main

import (
  "log"
  "errors"
)

type Danger struct {
  error
}

func main() {
  // the nil pointer issue has to do with struct embedding an error value that is nil
  d := &Danger{}
  log.Println(d)

  d = &Danger{errors.New("foobar")}
  log.Println(d)
}

приводит к

2009/11/10 23:00:00 %!v(PANIC=runtime error: invalid memory address or nil pointer dereference)
2009/11/10 23:00:00 foobar

https://play.golang.org/p/fBuN0XonX9v

Сегодня об этом говорится в интервью, и ни интервьюер, ни интервьюируемый не могли этого понять.

1 Ответ

0 голосов
/ 12 мая 2018

spec говорит:

При заданном типе структуры S и определенном типе T продвигаемые методы включаются в набор методов структуры следующим образом:

  • Если S содержит встроенное поле T, наборы методов S и * S включают в себя повышенные методы с приемником T. Набор методов * S также включает повышенные методы с приемником * T.

Документация fmt гласит:

Если операнд реализует интерфейс ошибки, будет вызван метод Error для преобразования объекта в строку, котораязатем будет отформатирован в соответствии с требованиями глагола (если есть).

Исходя из этого, мы можем заключить, что log.Println(d) будет вызывать повышенный метод Error из поля error.

Если поле error равно nil, вызов вызывает панику.

В документации fmt также говорится:

Если метод Error или String вызывает панику при вызовес помощью процедуры печати пакет fmt переформатирует сообщение об ошибкеот паники, украсив его с указанием, что он прошел через пакет fmt.

Текст %!v(PANIC=runtime error: invalid memory address or nil pointer dereference) - это значение украшенной паники.

...