AlgoMaster Logo

Basic Types (int, float, bool, string, rune, byte)

Last Updated: May 22, 2026

High Priority
7 min read

Go is statically typed, which means every value has a type the compiler knows about, and that type controls what you can do with the value. The language ships with a small set of built-in types that cover whole numbers, decimals, true/false, and text. This lesson is a tour of those types, what each one stores, how big they are, and when to pick one over another.

Integer Types

Integers are whole numbers, positive or negative. Go gives you eleven of them, which sounds like a lot until you realize they break into two simple groups: signed and unsigned, in four sizes each, plus a couple of special ones.

The signed integers are int8, int16, int32, and int64. The number in the name is the size in bits, so int8 is one byte and int64 is eight bytes. Signed means they can hold negatives.

The unsigned integers are uint8, uint16, uint32, and uint64. Same sizes, but they only hold zero and positive numbers. Trading the sign bit for one more bit of magnitude means a uint8 reaches 255 while an int8 only reaches 127.

Then there are the platform-sized ones: int and uint. These are either 32-bit or 64-bit depending on the machine Go is running on. On any modern desktop, laptop, or cloud server, they are 64-bit. On a 32-bit embedded target, they shrink to 32 bits. For almost all everyday code, you use int.

Finally, uintptr is an unsigned integer wide enough to hold the bit pattern of any pointer. You rarely touch it outside the unsafe package, but it shows up in the table for completeness.

Here is the full picture:

TypeSize (bits)RangeDefault ValueTypical Use
int88-128 to 1270Tight memory, small counters
int1616-32,768 to 32,7670Audio samples, small IDs
int3232-2,147,483,648 to 2,147,483,6470Unicode code points (rune)
int6464-9.2 x 10^18 to 9.2 x 10^180Large IDs, timestamps in nanoseconds
int32 or 64Same as int32 or int640Default for whole numbers
uint880 to 2550Raw bytes (alias byte)
uint16160 to 65,5350Network ports, small unsigned counts
uint32320 to 4,294,967,2950Hashes, packed flags
uint64640 to 1.8 x 10^190Big counters that never go negative
uint32 or 64Matches platform0Unsigned platform-native math
uintptr32 or 64Holds a pointer bit pattern0Low-level pointer math (unsafe)

In practice, int covers 95% of cases. Use a sized type when something forces your hand: a binary file format that specifies int32 fields, a network protocol that uses uint16 ports, or a memory budget that demands int8. Picking int16 for a loop counter just to "save space" is the kind of micro-optimization that buys you nothing and costs you readability.

Here is what integer usage looks like in everyday code:

stock := 42 gives you an int because untyped integer constants default to int. To get a different integer type you write its name as if it were a function: int64(2999).

Overflow

Go's integers wrap silently on overflow. There's no exception, no panic, just a value that has rolled over the top of its range to the bottom.

A uint8 can hold up to 255. Adding 10 to 250 produces 260, which doesn't fit, so the result wraps around to 4. Signed types behave the same way: pushing past the upper bound takes you to the lower bound.

Constants are different. If you try to store a constant that obviously doesn't fit, the compiler refuses:

The compiler can see the literal at build time and rejects it. Runtime arithmetic gets no such favor.

Floating Point Types

When you need decimals, Go offers two types: float32 and float64. Both follow the IEEE 754 standard, which is the same floating-point format your CPU's math hardware uses.

TypeSize (bits)PrecisionDefault ValueTypical Use
float3232~7 decimal digits0Graphics, sensor data, GPU buffers
float6464~15-17 decimal digits0Default for any decimal math

An untyped floating-point literal like 19.99 is a float64. If you write price := 19.99, you get a float64. To get a float32, you have to ask for it explicitly.

float64 is the right default for general use. float32 exists because some domains care about half the memory footprint (graphics, large numerical arrays) and accept the lower precision in exchange.

There is one well-known floating point quirk you should know about up front:

Neither 0.1 nor 0.2 can be represented exactly in binary, so the sum carries a tiny rounding error. This isn't a Go bug, it's how IEEE 754 works in every language. The takeaway: never use floats for money. For prices, store cents as integers (e.g., int64(1999) for $19.99) so addition and comparison are exact. We use float64 for prices in this lesson because it keeps examples simple, but production e-commerce code should use integer cents or a decimal library.

Boolean Type

The bool type holds exactly two values: true and false. There's no integer-to-bool coercion, no truthy strings, no nil booleans. Zero is not false, an empty string is not false, an empty slice is not false. The only things that are false are literally the value false and the zero value of a bool variable, which is also false.

The strictness pays off in conditionals. If you accidentally write if stock when you meant if stock > 0, Go stops you at compile time:

Other languages would happily treat 5 as truthy. Go forces the comparison to be explicit, which makes intent obvious and bugs rare.

String Type

A string in Go is an immutable sequence of bytes. The bytes are usually UTF-8 encoded text, but the type itself doesn't enforce that. As far as the language is concerned, a string is just a read-only byte sequence with a known length.

len() returns the byte count, not the character count. For pure ASCII text like the examples above, those are the same. For text with accented letters, Chinese characters, or emoji, they differ, and that's where rune enters the picture. For now, treat a string as bytes that usually represent text.

Strings are immutable. Once you have one, you can't change a character inside it. This fails to compile:

If you need a modified version, you build a new string.

The default value of a string is "", the empty string. That matters because it means an uninitialized string is safe to use, you won't get a nil-pointer panic the way you might in some other languages.

The %q verb prints the string with quotes, which is handy for telling apart "empty string" from "missing data."

rune and byte

Two of Go's built-in types are just nicknames for integer types you've already seen.

A byte is an alias for uint8. The two names refer to the exact same type. You use byte when you're thinking about raw data (file contents, network packets, raw bytes of a string), and uint8 when you're thinking about a small unsigned number.

A rune is an alias for int32. A rune represents a single Unicode code point, which is the proper way to talk about "a character" once you go beyond plain ASCII. The letter A is rune 65, the letter é is rune 233, and an emoji like a shopping bag is rune 128717. Storing those in an int32 works because Unicode currently fits in 21 bits, with room to spare.

A character literal like 'A' is an untyped rune constant. Storing it in a byte works because 65 fits in a uint8. Storing 'é' in a byte would fail because rune 233 fits, but storing 'shopping_bag_emoji' (code point 128717) in a byte would not.

Both are introduced here only so the names aren't a mystery when you see them.

Complex Numbers

For completeness: Go also has complex64 and complex128 for complex numbers with real and imaginary parts. Outside of scientific computing and signal processing, you'll almost never see them. We mention them so you recognize the names if they appear; the rest of this course doesn't use them.

Types Are Distinct

Different named types are different types in Go, even when they're the same size and represent the same kind of value.

int and int32 are both signed integers, and on a 64-bit machine int happens to be 64 bits, but the compiler still treats them as different types. You can't add them directly, compare them, or pass one where the other is expected. You have to convert explicitly.

This same rule applies between int and int64, between float32 and float64, between int and uint, and so on. Go does no implicit numeric conversion at all. If two values aren't the same named type, you have to convert one of them.

For now, just know that the rule exists and that the cure is conversion, not casting away the warning.

Choosing Between Types

Here's a quick decision guide for everyday e-commerce code:

A small example that puts most of the basic types together:

Five variables, five different basic types, no surprises. This is the shape of most Go programs: pick the simple type that fits the data, and don't think harder about it.