package main import ( "fmt" ) type Foo interface { Foo() } type Bar struct { Message string } func (b Bar) Foo() { fmt.Println(b.Message) } func main() { var b *Bar var f Foo f = b if f != nil { f.Foo() } }
Ответ от нейросети
sobes.tech AI
В данном коде есть тонкий момент с интерфейсом и nil-значениями в Go. Переменная b объявлена как указатель на Bar, но не инициализирована, то есть равна nil.
Когда мы присваиваем f = b, f становится интерфейсом, содержащим тип *Bar и значение nil.
Важно: интерфейс в Go считается nil только если и тип, и значение внутри интерфейса равны nil. В нашем случае тип *Bar не nil, а значение внутри nil.
Поэтому условие if f != nil будет истинным, и вызов f.Foo() произойдет. Но при вызове метода Foo() на b (который nil), метод Foo() определён с получателем по значению (func (b Bar) Foo()), а не по указателю. Вызов метода по значению на nil указателе невозможен и приведёт к панике.
Чтобы избежать паники, метод Foo() должен иметь получателя-указатель:
func (b *Bar) Foo() {
if b == nil {
fmt.Println("nil receiver")
return
}
fmt.Println(b.Message)
}
Тогда вызов f.Foo() на nil указателе будет корректно обработан.
Итог: в Go интерфейс с nil значением внутри не равен nil, и вызов метода с получателем по значению на nil указателе приводит к панике.