I found a good explanation in the book Go Programming Language (A. Donovan, B. Kernighan):
Although Go provides unsigned numbers and arithmetic, we tend to use
the signed int
form even for quantities that can’t be negative, such
as the length of an array, though uint
might seem a more obvious
choice. Indeed, the built-in len
function returns a signed int
, as in
this loop which announces prize medals in reverse order:
medals := []string{"gold", "silver", "bronze"}
for i := len(medals) - 1; i >= 0; i-- {
fmt.Println(medals[i]) // "bronze", "silver", "gold"
}
The alternative would be calamitous. If len
returned an unsigned
number, then i
too would be a uint
, and the condition i >= 0
would always be true by definition. After the third iteration, in
which i == 0
, the i--
statement would cause i
to become not −1,
but the maximum uint
value, and the evaluation of medals[i]
would
fail at run time, or panic, by attempting to access an element outside
the bounds of the slice. For this reason, unsigned numbers tend to be
used only when their bitwise operators or peculiar arithmetic
operators are required, as when implementing bit sets, parsing binary
file.