Description
I propose to add a new predeclared identifier zero
that is an untyped zero value. While nil
is an untyped zero value restricted to chan/func/interface/map/slice/pointer types, zero
would be an untyped zero value with no such restrictions.
The specific rules for zero
mimic nil
with fewer restrictions:
zero
is assignable to any variable of any type T that does not already have a short zero (0, "", nil), including when T is a type parameter with constraint any.- A value of any type T may be compared to
zero
when it cannot already be compared to a short zero (0, "", nil), again including when T is a type parameter with constraint any.
That's it. That's all the rules.
Note that assignability includes function arguments and return values: f(zero)
and return zero, err
are valid.
See CL 509995 for exact spec changes.
This proposal addresses at least three important needs:
-
Referring to a zero value in generic code. Today people suggest
*new(T)
, which I find embarrasingly clunky to explain to new users. This comes up fairly often, and we need something cleaner. -
Comparing to a zero value in generic code, even for non-
comparable
type parameters. This comes up less often, but it did just come up incmp.Or
(cmp: add Or #60204). -
Shortening error returns:
return zero, err
is nicer thanreturn time.Time{}, err
.
More generally, the zero value is an important concept in Go that some types currently have no name for. Now they would: zero
.
Because zero is not valid anywhere 0, "", or nil are valid, there will be no confusion about which to use.
I'm not claiming any originality in this proposal. Others have certainly suggested variants in the past, in quite long discussions. I'm not aware of any precise statement of the exact rules above, but I won't be surprised if one exists.
A brief comparison with earlier proposals:
- proposal: builtin: iszero #61129 proposes a builtin
iszero(x)
. This proposal usesx == zero
instead. - proposal: builtin: zero function #60695 proposes a generic zero function:
zero(T)
is a zero of type T. This proposal uses plainzero
which enables use in comparison and avoids a usually unnecessary(T)
. In non-assignment, non-conversion contexts where a type must be written, this proposal usesT(zero)
, which seems more idiomatic to me at least. - proposal: Go 2: universal zero value with type inference #35966 proposes an untyped zero value spelled
{}
. Later discussion in also consideredzero
. - proposal: spec: define _ on rhs as zero value #19642 proposes an untyped zero value spelled
_
.