Программа напечатает foo. Интерфейс i не равен nil, а метод Foo безопасен для nil-получателя, потому что не разыменовывает его.
Поведение интерфейса, содержащего 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-интерфейс.