Architecture-specific Numeric Types

February 21, 2023

In addition to the architecture-independent numeric types, Go provides three architecture-specific numeric types. Although there are far fewer of them, they often get a lot more usage.

Numeric Types

There is also a set of predeclared integer types with implementation-specific sizes:

uint     either 32 or 64 bits
int      same size as uint
uintptr  an unsigned integer large enough to store the uninterpreted bits of a pointer value

What does it mean for a type’s size to be architecture-dependent?

Well, it means that if you compile you code to run on, say, the 386 architecture, then int, and uint will hold 32 bits of data. But if you compile for the amd64 architecture, the same types will hold 64 bits of data.

But importantly, just because you may be compiling and running your code for the 386 architecture doesn’t mean that int and int32 are the same!

… Explicit conversions are required when different numeric types are mixed in an expression or assignment. For instance, int32 and int are not the same type even though they may have the same size on a particular architecture.

Okay, but why bother with this complexity?

In a word: efficiency.

While any CPU (not counting truly ancient ones) can handle both 32-bit and 64-bit numbers, they can’t do it with equal efficiency.

Manipulating 64-bit numbers on the 386 architecture involves manipulating two sets of 32-bit numbers, because the CPU’s native operations operate only on 32-bit numbers at a time.

So when should you use these architecture-specific types? Well, most of the time, actually. Generally, use int and uint for for loops or internal counters, unless there’s a risk of overflow (you’re counting large numbers that could exceed the min/max values of a 32-bit value), or you know you need a specific format for compatibility (i.e. writing the exact memory bits to the network or disk or similar).

Quotes from The Go Programming Language Specification, Version of January 19, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Integer context keys

We’re looking at different types for context keys. So far, we’ve looked at empty structs (struct{}), and found it to be less than ideal. Today, let’s consider integer context keys. This seems handy, right? type contextKey int const ( KeyUserID int = iota KeyTransactionID KeyMessageID . . . KeyFoo ) Let’s see how it stacks up to our 5 criteria: Must be comparable. ✅ No problem! Use minimal membory. ✅ int doesn’t have as small a memory footprint as struct{}’s zero bytes, but it’s still pretty small.


Size and alignment guarantees

This is it! The final email in my 2+ year series on the Go spec. Today we cover the last ~paragraph of the spec, not accounting for the appendix, which is mostly just a history of major changes to the spec. Size and alignment guarantees For the numeric types, the following sizes are guaranteed: type size in bytes byte, uint8, int8 1 uint16, int16 2 uint32, int32, float32 4 uint64, int64, float64, complex64 8 complex128 16 Most notably, int is omitted from this list.


IncDec statements

IncDec statements The “++” and “–” statements increment or decrement their operands by the untyped constant 1. As with an assignment, the operand must be addressable or a map index expression. IncDecStmt = Expression ( "++" | "--" ) . Most commonly you’ll see ++ and -- used on a simple variable. But as explained, it’s not strictly limited to that. These operators can be used on any addressable (numeric) expression.

Get daily content like this in your inbox!

Subscribe