tezvyn:

Explain Go's empty interface, safe usage, and runtime risks

AI-drafted, machine-checkedSource: go101.orgintermediate
WHAT IT TESTS

Go's universal value box and type erasure.

ANSWER OUTLINE

interface{} (alias any) holds values; unpack with type switches or ok assertions; risks are panics from bare assertions and nil interface vs nil concrete value confusion.

WHAT THIS TESTS: This question probes whether you understand Go's structural type system and the mechanics of value boxing. The empty interface is the extreme case of an interface type: it embeds no methods and therefore places no requirements on the concrete types that satisfy it. Since Go 1.18, the predeclared alias any is exactly equivalent to interface{}. Interviewers want to see that you know why this type is powerful, why it is dangerous, and how to recover type information safely at runtime.

A GOOD ANSWER COVERS: First, define the empty interface as a blank interface type whose type set includes all non-interface types, meaning every value can be boxed into it. Second, explain safe extraction techniques: a type switch for discriminating among multiple possible types, and a type assertion with the comma-ok idiom to avoid panics. Third, enumerate the runtime risks: a bare type assertion panics if the dynamic type does not match; a nil interface is not the same as a non-nil interface holding a nil pointer, which causes subtle bugs in equality checks and nil guards; and boxing introduces allocation and indirection overhead. Fourth, mention that any is simply an alias, not a distinct type.

COMMON WRONG ANSWERS: A red flag is using a bare type assertion such as v := x.(int) without the ok check, because that triggers a runtime panic when the dynamic type is wrong. Another mistake is claiming that any and interface{} behave differently or have different performance characteristics. Some candidates confuse the empty interface with generics or suggest it replaces type parameters, which misses the point: the empty interface erases type information, whereas generics preserve compile-time type safety. Finally, failing to explain the nil interface versus nil concrete value distinction reveals shallow experience with interface internals.

LIKELY FOLLOW-UPS: An interviewer might ask how the empty interface is implemented under the hood, which is the classic iface and eface runtime structures: a pair of pointers to type information and data. They might ask when to prefer generics over interface{} to avoid boxing and recover static typing. Another follow-up is how reflection with the reflect package interacts with empty interfaces, since reflect.ValueOf takes an empty interface and re-boxes the value.

ONE CONCRETE EXAMPLE: Imagine a function func printLength(v interface{}) that wants to call Len() if available. A safe implementation uses a type switch: switch s := v.(type) { case string: return len(s); case []int: return len(s); default: return -1 }. If instead you wrote n := v.([]int) and passed a string, the program panics. Similarly, if you pass a nil slice into an interface{}, the interface itself is non-nil because it carries type information, so checking if v == nil returns false even though the underlying slice is nil.

Read the original → go101.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.