Go's basic types are numbers, booleans and strings. Every variable has exactly one type, fixed at compile time, and Go never converts between types for you. %T prints the type of any value:
Notice 'G' prints as 71 with type int32: a single-quoted character is a rune, which is a number (the Unicode code point). rune is an alias for int32 (the same type under a second name), so %T reports int32. Likewise byte reports uint8.
Integers
| Type | Size | Range |
|---|---|---|
int8 | 8 bits | -128 to 127 |
int16 | 16 bits | -32,768 to 32,767 |
int32 | 32 bits | about -2.1 billion to 2.1 billion |
int64 | 64 bits | about -9.2 quintillion to 9.2 quintillion |
uint8 (byte) | 8 bits | 0 to 255 |
uint16 | 16 bits | 0 to 65,535 |
uint32 | 32 bits | 0 to about 4.3 billion |
uint64 | 64 bits | 0 to about 18.4 quintillion |
int, uint | 32 or 64 bits | platform word size |
uintptr | platform size | holds a pointer value, for low-level code |
Use int by default. len() returns int, slice indexes are int, and loop counters are int. On every 64-bit platform int is 64 bits. Reach for sized types when the size is part of a contract: int32 in a binary file format, uint8 for raw bytes, int64 for a Unix timestamp in nanoseconds.
Avoid unsigned types for quantities that "cannot be negative", such as counts. Subtracting past zero wraps to a huge number instead of producing a negative one you could catch.
Limits and overflow
The math package has a constant for every limit. At run time, integer arithmetic that overflows wraps around silently:
No panic, no error: 127 + 1 becomes -128. Only constant expressions are checked at compile time (var b int8 = 128 does not compile). If overflow is possible in your data, check before the operation or use math/big.
Integer literals
million := 1_000_000 // underscores for readability (Go 1.13+)
mask := 0xFF // hexadecimal
perm := 0o755 // octal (also the older form 0755)
flags := 0b1010 // binary
Floating-Point Numbers
| Type | Size | Precision |
|---|---|---|
float32 | 32 bits | about 6 to 9 significant digits |
float64 | 64 bits | about 15 to 17 significant digits |
A literal with a decimal point or exponent (2.5, 1e6) is float64 by default, and the math package takes and returns float64. Use it unless memory in a large array matters.
Floats are binary, so most decimal fractions are approximations:
Two rules follow. Never compare floats with == after arithmetic. And never store money in a float: use an integer number of cents, or a decimal library.
Dividing a float by zero gives +Inf, -Inf or NaN instead of panicking. Dividing an integer by zero panics at run time (runtime error: integer divide by zero), and a constant zero divisor is a compile error.
Booleans
bool holds true or false, and its zero value is false. Go does not treat numbers, empty strings or nil as booleans. if count {} is a compile error; write if count > 0 {}. The operators are &&, || and !, and && and || short-circuit.
Strings
A string is an immutable sequence of bytes, usually UTF-8 text. len(s) counts bytes, not characters:
é takes two bytes in UTF-8, so len reports 6 for five characters. Double-quoted strings process escapes like \n; backquoted raw strings do not, and can span lines. The strings page covers the strings package, and runes and bytes covers UTF-8 in depth.
byte and rune
| Alias | Same as | Holds |
|---|---|---|
byte | uint8 | one byte of raw data |
rune | int32 | one Unicode code point |
They are aliases, not new types: a byte and a uint8 are interchangeable without conversion. The names say what the number means.
Complex Numbers
Go has built-in complex types, complex64 and complex128, with real, imag and the math/cmplx package:
Few programs need them, but signal processing and some numeric code do.
Composite and Reference Types
The basic types combine into composite ones. Each has its own page:
| Type | Example | Zero value |
|---|---|---|
| array | [3]int | three zeros |
| slice | []int | nil |
| map | map[string]int | nil |
| struct | struct{ X, Y int } | every field zeroed |
| pointer | *int | nil |
| function | func(int) int | nil |
| channel | chan int | nil |
| interface | error, any | nil |
any is an alias for interface{} (since Go 1.18) and can hold a value of any type.
Named Types
You can define a new type from an existing one. It has the same representation but is a distinct type, and it can have methods:
type Celsius float64
type UserID int64
var t Celsius = 21.5
var f float64 = t // compile error: cannot use t (variable of float64 type Celsius) as float64 value in variable declaration
That strictness is the point: a UserID cannot be passed where an OrderID is expected by accident. Convert explicitly when you mean it: float64(t). See type conversion for the rules and the strconv functions for going between numbers and strings.
Zero Values
Every type has a zero value, which is what a variable holds before you assign anything: 0 for numbers, false for bool, "" for strings, and nil for pointers, slices, maps, channels, functions and interfaces. There are no uninitialized variables in Go.
Frequently Asked Questions
How big is an int in Go?
int and uint are 64 bits on 64-bit platforms (amd64, arm64) and 32 bits on 32-bit platforms. If you need a fixed size, for a file format or network protocol, use int32, int64, uint8 and so on. For ordinary counters, indexes and lengths, use int.
How do I print the type of a variable in Go?
Use the %T verb: fmt.Printf("%T\n", x) prints int, float64, []string, main.User and so on. In code, reflect.TypeOf(x) returns the same information as a value you can inspect.
What is the difference between byte and rune in Go?
byte is an alias for uint8 and holds one byte of raw data. rune is an alias for int32 and holds one Unicode code point. A string is a sequence of bytes; ranging over it with for range decodes it into runes.
Should I use float32 or float64 in Go?
Use float64 unless you have a reason not to. It is the default type of floating-point literals, the type the math package works with, and has about 15 to 17 significant decimal digits of precision against about 6 to 9 for float32. Choose float32 only to halve memory in large arrays or to match an external format.
What is the maximum value of int in Go?
Use the constants in the math package: math.MaxInt (9223372036854775807 on 64-bit platforms), math.MinInt, math.MaxInt64, math.MaxUint32 and so on. Arithmetic that goes past the limit wraps around silently at run time; it does not panic.