When does comparing two interface values panic? What does this print?
Question 99HardGo 1.22 to 1.25
Two interface values are equal when their dynamic types are identical and their dynamic values are equal, or when both are nil. If the dynamic types are the same and that type is not comparable (slice, map, func, or a struct or array containing one), the comparison panics at runtime. It compiles fine, because the compiler cannot know the dynamic type.
var a, b any = 1, 1
fmt.Println(a == b) // true
var c, d any = 1, int64(1)
fmt.Println(c == d) // false: different dynamic types, no panic
var e, f any = []int{1}, "x"
fmt.Println(e == f) // false: types differ, values never compared
var g, h any = []int{1}, []int{1}
fmt.Println(g == h) // panic: runtime error: comparing uncomparable type []int
m := map[any]bool{}
m[[]int{1}] = true // panic: runtime error: hash of unhashable type []int
type S struct{ tags []string }
var x, y error = nil, nil
_ = x == y // true
var s1, s2 any = S{}, S{}
_ = s1 == s2 // panic: comparing uncomparable type main.S
This matters in practice:
- A typed error defined as a struct with a slice field makes
err == ErrXorerrors.Ispanic if both sides hold that type.errors.Isguards against this with a comparability check. Hand-written==comparisons do not. - Generic code with the
comparableconstraint accepts interface types (Go 1.20+), so==in generic code can also panic at runtime.
reflect.DeepEqual avoids the panic, or you can check reflect.TypeOf(x).Comparable() before using ==. slices.Equal on a []any does not help: it uses == on each element and panics the same way.
More on Interfaces, Methods & Embedding
- Q97What's wrong with this
String()method? When doesfmtcallString()orError()? - Q98Design custom errors in Go. Explain wrapping,
errors.Is,errors.Asand multi-error trees. - Q100Does converting a value to an interface allocate? How do interfaces affect escape analysis and performance?
- Q101What's the difference between a method value and a method expression? What does this print?
- Q102On which types can you declare methods? Can you add a method to
int,time.Time, a pointer type, or an interface? - Q103How does the "optional interface" (interface upgrade) pattern work? Give a stdlib example and its pitfall.