Go

Can you compare functions in Go? Why is a func only comparable to nil, and how does that affect using funcs as map keys?

Question 554HardGo 1.22 to 1.25

Func values can only be compared to nil. f == g is a compile error ("func can only be compared to nil"), and map[func()]int is "invalid map key type". The reason: function equality has no clear meaning. Two closures from the same literal share code but capture different environments. The compiler may inline, deduplicate or specialize functions. Method values (t.M) allocate new closures. Any definition would either be surprising or would block optimizations.

What does this do?

f := func() {}
var a, b any = f, f
fmt.Println(a == b) // compiles, but panics at runtime:
// runtime error: comparing uncomparable type func()

m := map[any]int{}
m[f] = 1 // panics: runtime error: hash of unhashable type func()

Putting a func inside an interface moves the check from compile time to runtime, and the same applies to structs that contain func fields. Workarounds: key the map by a name or ID (map[string]Handler). Or wrap the func in a struct and use the pointer as identity (map[*Hook]struct{}), which is how you make "unsubscribe" work for callbacks. reflect.ValueOf(f).Pointer() returns the code pointer, but all closures from one literal share it, so it is not a reliable identity. Bonus: embedding _ [0]func() in a struct makes the struct non-comparable at zero size cost, which is useful for preventing == on types where it would be wrong.

More on Go Idioms, Design Patterns & Language Design

All 16 Go Idioms, Design Patterns & Language Design questions