How do you get and check the zero value of a type parameter T?
Question 121MediumGo 1.22 to 1.25
You cannot write return nil, and you cannot write T{} for an arbitrary T. nil is not valid for int, and composite literals need a core type. Use one of these idioms:
func First[T any](xs []T) (T, bool) {
if len(xs) == 0 {
var zero T // idiom 1
return zero, false
}
return xs[0], true
}
func Default[T any]() T { return *new(T) } // idiom 2 (terse, allocation optimized away)
// Comparing with zero requires comparable
func IsZero[T comparable](v T) bool {
var zero T
return v == zero
}
// For any T (slices, maps, funcs), fall back to reflect
func IsZeroAny[T any](v T) bool {
return reflect.ValueOf(&v).Elem().IsZero()
}
Gotchas:
IsZero[any](x)compiles, but it can panic if the dynamic type is not comparable (see thecomparablequestion).reflect.ValueOf(v)on a nil interface gives an invalid Value, which is why the example uses&v.- Returning
(T, bool)or(T, error)is the idiomatic way to report "not found". It beats returning a sentinel zero.
More on Generics
- Q119How does type inference work? When does it fail, and how do you order type parameters to make partial instantiation pleasant?
- Q120Can you store a generic function in a variable or pass it around without instantiating it?
- Q122What does this print? (nil checks inside generic code)
- Q123What does this print? (type switch on a type parameter)
- Q124Why doesn't Go allow type parameters on methods? What do you do instead?
- Q125How do you write methods on a generic type? What is wrong with
func (s Stack[int]) Sum() int?