Поведение интерфейса, содержащего nil‑указатель

Программа напечатает foo. Интерфейс i не равен nil, а метод Foo безопасен для nil-получателя, потому что не разыменовывает его.

Короткий ответ

Что ответить на собеседовании

Программа напечатает foo. Интерфейс i не равен nil, а метод Foo безопасен для nil-получателя, потому что не разыменовывает его.

Подробный разбор

Ответ с пояснениями

Условие

Нужно понять, какой результат выведет следующая программа.

type I interface {
  Foo()
}

type S struct{}

func (s *S) Foo() {
  fmt.Println("foo")
}

func Build() I {
  var res *S
  return res
}

func main() {
  i := Build()
  if i != nil {
    i.Foo()
  } else {
    fmt.Println("nil")
  }
}

Ответ

Программа напечатает foo. Интерфейс i не равен nil, а метод Foo безопасен для nil-получателя, потому что не разыменовывает его.

Build возвращает интерфейс I с динамическим типом *S и нулевым указателем. Поэтому проверка i != nil истинна.

В Go вызов метода с указателем-получателем не обязан паниковать при nil: всё зависит от тела метода. Здесь Foo только печатает константу. Если бы он обращался к полям через s, без проверки nil могла бы возникнуть panic. Для обозначения отсутствия объекта фабрика должна явно возвращать nil-интерфейс.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее