Sobes.tech
Senior

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

Answer from AI

This code contains a subtle point regarding interfaces and nil values in Go. The variable b is declared as a pointer to Bar, but not initialized, so it is nil.

When we assign f = b, f becomes an interface containing the type *Bar and the value nil.

Important: an interface in Go is considered nil only if both the type and the value inside the interface are nil. In our case, the type *Bar is not nil, but the value inside is nil.

Therefore, the condition if f != nil will be true, and f.Foo() will be called. But when calling the method Foo() on b (which is nil), the method Foo() is defined with a value receiver (func (b Bar) Foo()), not a pointer receiver. Calling a value receiver method on a nil pointer is impossible and will cause a panic.

To avoid the panic, the Foo() method should have a pointer receiver:

func (b *Bar) Foo() {
    if b == nil {
        fmt.Println("nil receiver")
        return
    }
    fmt.Println(b.Message)
}

Then, calling f.Foo() on a nil pointer will be handled correctly.

In summary: in Go, an interface with a nil value inside is not equal to nil, and calling a method with a value receiver on a nil pointer leads to a panic.