Go

What happens when you call a value-receiver method through an interface that holds a nil pointer?

Question 107HardGo 1.22 to 1.25
type V struct{ n int }

func (v V) Get() int { return 42 } // value receiver, never reads v.n

type Getter interface{ Get() int }

//go:noinline
func call(g Getter) int { return g.Get() }

func main() {
    var p *V
    var g Getter = p      // legal: *V's method set includes V's methods
    fmt.Println(g != nil) // ?
    fmt.Println(call(g))  // ?
}

Output:

true
panic: value method main.V.Get called using nil *V pointer

*V satisfies Getter because the method set of *V includes value-receiver methods. The compiler makes this work by generating a wrapper method (*V).Get that dereferences the pointer, copies the V and calls V.Get. The itab points at that wrapper. When the pointer is nil, the wrapper cannot make the copy, so it calls runtime.panicwrap. That happens even though Get never touches a field.

A pointer-receiver method, by contrast, is called with a nil receiver and can handle it (as (*bytes.Buffer).String does). If the compiler can see the concrete type and devirtualizes the call, or if you call p.Get() directly, you get the ordinary invalid memory address or nil pointer dereference panic instead.

The interviewer is checking that you know value methods are reachable from pointers only through auto-generated wrappers, and that a method designed to be nil-safe needs a pointer receiver.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions