与Go语言中的特定类型(int64 / uint64)相比,常规类型(int / uint)有什么优势?

I understand that int and uint are 64bit signed / unsigned integers - just like int64 / uint64. And I also understand that int is not simply an alias for int64 (like byte -> uint8 is), so int64 would need to be converted to int and visa versa when applicable. However what are the benefits of using one over the other? Is there any run time performance penalty for using the general types?

Sorry if this is a common question - I had Googled for the answer (and searched on here too) as I'd have thought others might have cropped up before but didn't find anyone answer the question in terms of how they affect performance (if at all), memory usage (I'm guessing not if they're both 64bit integers?) nor how the compiler treats them.

edit: I'm aware that int / unit are 32bit on 32bit architectures. For the sake of brevity and comparing like for like, I was assuming this is a 64bit Golang environment.

int and uint are only 64-bit on 64-bit architectures. On 32-bit architectures they are 32 bits.

The general answer is that, unless you need a certain precision, sticking with datatypes that are the same size as a word on the current architecture (e.g. 32 bits on a 32-bit architecture) is typically slightly more efficient.

In addition to int being of "native" size slice and array indices are int and not int64 or int32.

int and uint correspond to the maximum possible length of basic Go data structures in a Go implementation and runtime. The length of string, map[K]T, []T and chan T always fits into an int, and the capacity of []T and chan T always fits into an int.

An allocation via make is bound to return an object with length and capacity that always fit into an int. The built-in function append returns a slice with length and capacity that never exceed an int. The length (the number of defined keys) of a map after inserting a new key-value pair always fits into an int.

The main benefit is that int and uint are the smallest (in terms of bitsize) data types which are safe to use in a Go program in conjunction with common Go data types such as slices and maps.

The size of int is independent from the size of a pointer *T. The integer type corresponding to *T is uintptr. In theory, a Go implementation could choose to map int to int16 - many Go programs would remain to work correctly, but limiting the size of allocations to 15 bits may be too restrictive and would cause runtime panics.

On 64-bit architectures Go 1.0 has int and uint 32 bits long, Go 1.1 64 bits long (see Go 1.1 Release Notes). This change will increase the memory usage of some Go programs on 64-bit architectures..

Explicitly using int64 instead of int in a Go program can make it slower under Go 1.0 and on 32-bit architectures because:

  • of conversions between int and int64

  • the performance of certain CPU instructions, such as division, depends on the size of operands

Explicitly using int64 instead of int in a Go program can make it faster under Go 1.0 on 64-bit architectures because:

  • The compiler can generate more efficient code for address and offset computation if all operands are 64-bit. Mixing 32-bit and 64-bit operands when computing addresses and offsets is slower.

Using uint16 as an index when accessing [1<<16]T allows the compiler to remove bound checking instructions.