Go Tutorials: Numeric Types Beginner Tutorial

Go has four main families of numeric types:

Numbers
│
├── Signed Integers
│   ├── int
│   ├── int8
│   ├── int16
│   ├── int32
│   └── int64
│
├── Unsigned Integers
│   ├── uint
│   ├── uint8
│   ├── uint16
│   ├── uint32
│   └── uint64
│
├── Floating Point
│   ├── float32
│   └── float64
│
└── Complex Numbers
    ├── complex64
    └── complex128

The simplest way to remember them is:

Type familyStoresExample
intWhole numbers, positive or negative-10, 0, 25
uintWhole numbers, zero or positive0, 25, 100
floatDecimal numbers10.5, 3.14
complexReal + imaginary numbers3 + 4i

1. Signed Integers

A signed integer can contain:

negative numbers
zero
positive numbers

Example:

var temperature int = -10

Here -10 is allowed because int is signed.

Signed integer types

TypeSizeApproximate range
int88 bits-128 to 127
int1616 bits-32,768 to 32,767
int3232 bits-2.1 billion to +2.1 billion
int6464 bitsVery large
int32 or 64 bitsDepends on system

For most normal programming, use:

int

Example

package main

import "fmt"

func main() {
    var age int = 40
    var temperature int = -5
    var balance int = -1000

    fmt.Println("Age:", age)
    fmt.Println("Temperature:", temperature)
    fmt.Println("Balance:", balance)
}

Output:

Age: 40
Temperature: -5
Balance: -1000

When should I use int?

Use int for normal whole-number calculations.

Typical use cases:

age := 40
users := 500
items := 10
temperature := -5
score := 95

For example, loop counters normally use int:

for i := 0; i < 10; i++ {
    fmt.Println(i)
}

Simple rule

If you need a normal whole number and don’t have a special requirement, use int.


2. int8

int8 is a very small signed integer.

var temperature int8 = -20

Range:

-128 to 127

Example:

package main

import "fmt"

func main() {
    var temperature int8 = -20

    fmt.Println(temperature)
}

Use cases

You may use int8 when:

  • Memory layout matters
  • Reading binary data
  • Working with low-level protocols
  • Interacting with hardware

For normal application development, you usually do not need int8.


3. int16

Range:

-32768 to 32767

Example:

var altitude int16 = -500

Possible use cases:

  • Binary file formats
  • Network protocols
  • Hardware data
  • Memory-sensitive structures

Again, normal application code usually uses int.


4. int32

Example:

var population int32 = 1000000

One very important use of int32 in Go is Unicode characters.

Go has an alias:

rune = int32

For example:

package main

import "fmt"

func main() {
    var letter rune = 'A'

    fmt.Println(letter)
    fmt.Printf("%c\n", letter)
}

Output:

65
A

So:

rune
 ↓
int32
 ↓
Unicode character

5. int64

int64 can store very large whole numbers.

Example:

var population int64 = 8000000000

Use cases include:

  • Very large counters
  • Unix timestamps
  • Database IDs
  • File sizes
  • Large financial quantities expressed in smallest units

Example:

package main

import "fmt"

func main() {
    var fileSize int64 = 5_000_000_000

    fmt.Println(fileSize)
}

Notice this:

5_000_000_000

Go allows _ to make large numbers easier to read.

It is the same as:

5000000000

6. Unsigned Integers

Unsigned integers cannot contain negative numbers.

Signed:

-10  -5  0  5  10


Unsigned:

0  5  10  100

Example:

var users uint = 100

This works.

But:

var users uint = -100

doesn’t work because uint cannot represent negative values.

Unsigned integer types

TypeMinimumMaximum
uint80255
uint16065,535
uint320~4.29 billion
uint640Very large
uint0System dependent

7. uint

Example:

package main

import "fmt"

func main() {
    var numberOfUsers uint = 500

    fmt.Println(numberOfUsers)
}

Use cases can include values that are inherently non-negative.

For example:

bit manipulation
binary protocols
hardware registers
memory-related values

But here’s an important Go practice:

Don’t automatically use uint just because a value cannot logically be negative.

For example, for the number of students:

students := 50

Using int is normally easier.


8. uint8

uint8 has an important role in Go.

Range:

0 → 255

Go has an alias:

byte = uint8

Therefore:

var x byte = 65

is essentially:

var x uint8 = 65

This is why byte arrays are common when working with:

  • Files
  • Network data
  • Images
  • Strings
  • Raw binary data

Example:

package main

import "fmt"

func main() {
    var value uint8 = 255
    var letter byte = 'A'

    fmt.Println(value)
    fmt.Println(letter)
}

Output:

255
65

Remember:

byte
 ↓
uint8
 ↓
0-255

9. Floating-Point Numbers

Integers cannot store decimal fractions.

For example:

10
20
-5

are integers.

But:

10.5
3.14
99.99

are floating-point numbers.

Go provides:

float32
float64

10. float32

float32 uses 32 bits.

Example:

package main

import "fmt"

func main() {
    var temperature float32 = 36.5

    fmt.Println(temperature)
}

Typical use cases:

  • Graphics
  • Games
  • Scientific data where 32-bit precision is sufficient
  • Large arrays where memory usage matters
  • APIs/libraries requiring 32-bit floats

For ordinary Go applications, however, float64 is usually preferred.


11. float64

float64 provides much higher precision.

Example:

package main

import "fmt"

func main() {
    var price float64 = 199.99
    var pi float64 = 3.141592653589793

    fmt.Println("Price:", price)
    fmt.Println("Pi:", pi)
}

Use cases:

measurements
percentages
statistics
scientific calculations
coordinates
averages
general decimal calculations

Important

When you write:

price := 99.99

Go normally infers:

float64

So:

price := 99.99

is effectively similar to:

var price float64 = 99.99

Beginner rule

Use float64 unless you specifically need float32.


12. Be Careful Using Floats for Money

This looks natural:

price := 10.99

But floating-point numbers cannot represent every decimal value perfectly.

For example:

package main

import "fmt"

func main() {
    result := 0.1 + 0.2

    fmt.Printf("%.20f\n", result)
}

You may see something like:

0.30000000000000004441

Therefore, for exact money calculations, applications commonly store money in the smallest currency unit.

Instead of:

price := 10.99

you might store:

priceInCents := 1099

or for Indian rupees:

priceInPaise := 1099

representing:

₹10.99

13. Complex Numbers

Go also supports complex numbers.

A complex number consists of:

real part + imaginary part

Example:

3 + 4i

Here:

3 = real part
4 = imaginary part
i = imaginary unit

Go has:

complex64
complex128

14. complex64

complex64 consists approximately of:

float32 + float32

Example:

package main

import "fmt"

func main() {
    var number complex64 = 3 + 4i

    fmt.Println(number)
}

Output:

(3+4i)

Typical use cases:

  • Signal processing
  • Electrical engineering
  • Scientific calculations
  • Fourier transforms
  • Mathematical simulations

Most normal web/backend programs never need this type.


15. complex128

complex128 uses greater precision.

Conceptually:

complex128
    │
    ├── float64 real part
    │
    └── float64 imaginary part

Example:

package main

import "fmt"

func main() {
    var number complex128 = 3 + 4i

    fmt.Println("Number:", number)
    fmt.Println("Real:", real(number))
    fmt.Println("Imaginary:", imag(number))
}

Output:

Number: (3+4i)
Real: 3
Imaginary: 4

Go provides built-in functions:

real()
imag()
complex()

For example:

x := complex(3.0, 4.0)

creates:

3 + 4i

16. One Complete Example

This example demonstrates all four major families.

package main

import "fmt"

func main() {

    // --------------------------------
    // 1. SIGNED INTEGER
    // --------------------------------

    // Can store negative and positive whole numbers.
    var temperature int = -10

    // --------------------------------
    // 2. UNSIGNED INTEGER
    // --------------------------------

    // Can store only zero or positive whole numbers.
    var packetValue uint = 255

    // --------------------------------
    // 3. FLOATING POINT
    // --------------------------------

    // Can store decimal numbers.
    var price float64 = 199.99

    // --------------------------------
    // 4. COMPLEX NUMBER
    // --------------------------------

    // Stores real + imaginary values.
    var signal complex128 = 3 + 4i

    fmt.Println("Temperature:", temperature)
    fmt.Println("Packet value:", packetValue)
    fmt.Println("Price:", price)
    fmt.Println("Signal:", signal)

    fmt.Println("Signal real part:", real(signal))
    fmt.Println("Signal imaginary part:", imag(signal))
}

Output:

Temperature: -10
Packet value: 255
Price: 199.99
Signal: (3+4i)
Signal real part: 3
Signal imaginary part: 4

17. int vs uint vs float64 vs complex128

This comparison is the most important part to remember.

RequirementBest choiceExample
Normal whole numberint40
Negative whole numberint-10
Low-level non-negative integeruint family255
Raw bytebyte / uint865
Unicode characterrune / int32'你'
Decimal numberfloat6410.25
Memory-sensitive decimalfloat3210.25
Complex mathematicscomplex1283 + 4i
Lower-precision complex numbercomplex643 + 4i

18. Type Conversion

Go does not automatically mix numeric types.

For example:

var x int = 10
var y float64 = 20.5

You cannot simply do:

result := x + y

because:

x = int
y = float64

You have to convert one type.

package main

import "fmt"

func main() {
    var x int = 10
    var y float64 = 20.5

    result := float64(x) + y

    fmt.Println(result)
}

Output:

30.5

Think:

x
10
│
│ float64(x)
▼
10.0
     +
20.5
─────
30.5

19. Overflow

Every numeric type has a limit.

For example:

uint8

can only hold:

0 → 255

So this is invalid:

var x uint8 = 300

because:

300 > 255

Similarly:

int8

supports:

-128 → 127

Therefore:

var x int8 = 200

is invalid.


20. Special Aliases: byte and rune

Two names appear constantly in Go:

byte
rune

They aren’t entirely new numeric storage formats.

byte = uint8
rune = int32

Think of them as meaningful names:

TypeActuallyMeaning/use
byteuint8Raw byte/data
runeint32Unicode character

Example:

package main

import "fmt"

func main() {
    var b byte = 'A'
    var r rune = '你'

    fmt.Println(b)
    fmt.Printf("%c\n", b)

    fmt.Println(r)
    fmt.Printf("%c\n", r)
}

21. Practical Real-World Examples

Age

age := 40

Use:

int

Number of users

users := 1000

Usually:

int

Temperature

temperature := -5

Use:

int

or if decimals are needed:

temperature := -5.7

Use:

float64

Height

height := 175.5

Use:

float64

File size

var size int64 = 10_000_000_000

int64 can be useful.

Network byte

var packetByte byte = 255

Use:

byte / uint8

Unicode character

var character rune = '日'

Use:

rune / int32

Scientific complex value

var signal complex128 = 2.5 + 3.7i

Use:

complex128

22. The Rule You Should Remember

As a beginner, don’t overthink all the numeric types.

For approximately 90% of normal Go application code, think:

Whole number
     ↓
    int


Decimal number
     ↓
  float64


Raw data / bytes
     ↓
 byte / uint8


Unicode character
     ↓
 rune / int32


Complex mathematics
     ↓
 complex128

And only deliberately choose:

int8
int16
uint16
float32
complex64
...

when you have a specific reason such as memory layout, binary protocols, hardware, APIs, or scientific requirements.

Final Cheat Sheet

// Normal whole number
age := 40                    // int

// Negative whole number
temperature := -10           // int

// Decimal
price := 99.99               // float64

// Large integer
var size int64 = 5_000_000_000

// Raw byte
var data byte = 255          // byte = uint8

// Unicode character
var letter rune = '日'       // rune = int32

// Unsigned low-level number
var flags uint32 = 100

// Complex mathematics
var signal complex128 = 3 + 4i

The most useful mental model is simply:

int = whole numbers → float64 = decimal numbers → byte = raw data → rune = characters → complex128 = complex mathematics.

Related Posts

Go Tutorials: Go Methods

Go methods become much easier once you understand one idea: A method is simply a function attached to a type. And the important rule is: A receiver…

Read More

Go Tutorials: Modules, Packages, Subpackages, Submodules, and Workspaces

This tutorial gives you one complete mental model for: The most important idea is: And sometimes: These two designs are very different. 1. What is a Go…

Read More

Go Tutorials: Go Testing, Benchmarking, and Profiling

These three topics become much easier once you separate the questions they answer: Topic Main question Main Go tool Result Testing Does my code work correctly? go…

Read More

Go Tutorials: Generics

1. What are Generics? Generics let you write one piece of code that works with multiple types while keeping Go’s compile-time type safety. Suppose you want a…

Read More

Go Concurrency Management Made Simple

This tutorial covers: The goal is: One concept → one purpose → one complete runnable example. Every example is independent. Save any example as: and run: 0….

Read More

Go Tutorials: Concurrency Made Simple

This tutorial covers: The goal is simple: One concept → one mental model → one complete example. Every example is independent. You can copy it into main.go…

Read More