Hard15 minGo Fundamentals
UpdatedAug 4, 2026
Edit

Interfaces and the Nil Trap

CONCEPTS:Go Interfaces and Nil

Question Variations

  • "How does a Go type implement an interface?"
  • "Why can `err != nil` when the returned pointer is nil?"
  • "What is the difference between a nil interface and an interface holding a nil pointer?"
  • "How do pointer and value receiver method sets affect interface satisfaction?"

Why This Is Asked

Go’s interfaces are deliberately simple, but their runtime representation creates a frequent source of bugs. This question evaluates whether you understand implicit implementation, method sets, and why an interface can appear non-nil while containing a nil pointer.

Key Concepts

  • Types satisfy interfaces implicitly by implementing the required methods.
  • An interface value stores a dynamic type and a dynamic value.
  • A nil interface has neither a dynamic type nor a dynamic value.
  • An interface containing a typed nil pointer has a type and is therefore non-nil.

Question Variations

  • “How does a Go type implement an interface?”
  • “Why can err != nil when the returned pointer is nil?”
  • “What is the difference between a nil interface and an interface holding a nil pointer?”
  • “How do pointer and value receiver method sets affect interface satisfaction?”

Answers by Technology

+ Add Variant
GoImprove this answer ✏️

Expected Answer (Go 1.26.5)

Go interfaces are satisfied implicitly: a type implements an interface when its method set contains the interface’s methods. An interface value is conceptually a pair of dynamic type and dynamic value. It is only equal to nil when both are absent.

Assigning a typed nil pointer to an interface supplies a dynamic type, so the interface is non-nil even though its dynamic value is nil.

package main

import "fmt"

type Notifier interface {
	Notify()
}

type EmailNotifier struct{}

func (*EmailNotifier) Notify() {}

func main() {
	var email *EmailNotifier
	var notifier Notifier = email

	fmt.Println(email == nil)    // true
	fmt.Println(notifier == nil) // false
}

Avoid returning typed nil pointers as error or interface values when callers expect a nil interface to represent success. Return a literal nil interface on success instead.

Why It Matters

This pitfall is especially dangerous for error returns: if err != nil can enter an error path even though the underlying pointer is nil. Interfaces also shape how Go code is tested and decoupled from concrete implementations.

Common Mistakes

  • Expecting explicit implements declarations: Go uses structural, implicit interface satisfaction.
  • Returning a typed nil pointer as an error: The resulting interface is non-nil.
  • Ignoring receiver type: Methods with pointer receivers are not in the method set of the non-pointer value type.

Follow-up Questions

  • Why are small interfaces preferred in Go? (Answer: They are easier to satisfy, mock, and keep focused on a caller’s actual needs.)
  • How can you check a dynamic interface type? (Answer: Use a type assertion or a type switch.)