Why len(*Type) return int not uint ?

278 views
Skip to first unread message

zuxiong lin

unread,
Dec 23, 2014, 10:58:28 PM12/23/14
to golan...@googlegroups.com
I am Curious about the Title Question.

Dave Cheney

unread,
Dec 23, 2014, 11:01:32 PM12/23/14
to golan...@googlegroups.com
Because it would make a for loop very inconvenient to type

for i := 0; i < len(something); i++ {
// something
}

Would not complie.

The very wise Alan Donovan said recently, use signed types for everything except bit manipulation.

Dmitri Shuralyov

unread,
Dec 24, 2014, 12:26:22 AM12/24/14
to golan...@googlegroups.com
It would also be hard to do a reverse loop:

for i := len(something) - 1; i >= 0; i-- { 
    // ...
}

Would be an infinite loop if i is unsigned.

That demonstrates the following observation. While values of len are always non-negative, the operations that are done with output of len may sometimes result in negative numbers. You don't want to limit yourself from being able to use -1, etc.

minux

unread,
Dec 24, 2014, 10:52:15 PM12/24/14
to zuxiong lin, golang-nuts
On Tue, Dec 23, 2014 at 10:58 PM, zuxiong lin <linzuxi...@gmail.com> wrote:
I am Curious about the Title Question.
This has been asked again and again.

Search the archive for more detailed explanations.

The short answer is:
Basically, due to the way Go's type system works, we need to use the same type of
integer for both index and length.

Both kind of the integer type (unsigned and signed) have their own subtle points where
changing 1 in the binary representation will change a lot in the number it actually represents.

For signed numbers, the point is at largest integer. for example, adding one to the largest
positive integer will make it the smallest negative integer.

For unsigned numbers, the point is at zero. Subtracting one from zero will make the largest
unsigned number.

We want to chose one type of integer where most of the operations will not come near those
subtle points.

For length/index of an object, it's easy for it to be close to zero, so using unsigned means
we're pretty near the subtlety, a off-by-one error might make your program crash by trying to
allocate all the memory in your machine or make your loop endless, whereas it's hard for the
length/index to reach the largest representable positive number (the runtime allocation routine
will panic before you even come close to that due to out-of-memory situations).

Even though it might seem that using unsigned integer to represent length is the most
natural thing to do, using unsigned integer to represent index is not something you'd like.
Others have already provided examples for that.

Some might argue that using signed integer loses half of the numbers. But that is unlikely
to matter much.

On 64-bit systems, have you seen 2^64 bytes of memory? In fact, most current cpus only
implements 48-bit of the physical memory space.

On 32-bit systems, it's true that you can't have a byte slice or array larger than 2G, but
as soon as your increase the size of the element to more than 1 byte, 2G elements will
be more than enough to hit the address space limitation of 32-bit systems.
(Not to mention that on real 32-bit systems, user space programs typically only have
~3GB of address space available, and to manage 3GB heap, Go's current runtime will
need 384MB of bitmap, and if we include other memory overheads, it's impossible for
a 32-bit Go programs to have close to 2GB of usable memory on a real 32-bit machine.
(By real 32-bit machine, I mean those that are using 32-bit only processors, because on
64-bit OSes, 32-bit processes can have the entire 4GB of VM space, but it will make more
sense to just use 64-bit Go on those systems)
Reply all
Reply to author
Forward
0 new messages