Skip to main content

What’s the difference between int, int32, and int64?

Brief Answer

TypeSizeValue range
int32always 4 bytes (32 bits)from -2,147,483,648 to 2,147,483,647
int64always 8 bytes (64 bits)from approximately -9.2 × 10¹⁸ to 9.2 × 10¹⁸
intdepends on the platform: 4 bytes on 32-bit systems and 8 bytes on 64-bit systemsdepends on its size

The main differences are memory size, value range, and portability across platforms.

What Do “32 Bits” and “64 Bits” Mean?

A bit is a unit of data that can store either 0 or 1. The more bits allocated to a number, the more different values it can represent.

Because these are signed integers and can store negative numbers, their range is split approximately in half: one half for negative values and the other half for positive values.

// int32: 4 billion / 2 ≈ 2.1 billion in each direction
// int64: 1.8 × 10¹⁹ / 2 ≈ 9.2 × 10¹⁸ in each direction

int32 and int64 Have Fixed Sizes

These types are guaranteed to have the same size on every platform. This is important when:

var a int32 = 100
var b int64 = 100

fmt.Println(unsafe.Sizeof(a)) // 4, always
fmt.Println(unsafe.Sizeof(b)) // 8, always

unsafe.Sizeof is a built-in function that returns the size of a value in bytes.

The Size of int Depends on the Platform

The int type is the convenient default integer type. Its size is selected by the compiler depending on the target system:

var x int = 42
fmt.Println(unsafe.Sizeof(x)) // most likely 8 on your machine

Even though int and int64 have the same size on a 64-bit system, they are still different types for the compiler. You cannot assign one to the other without an explicit conversion:

var a int = 10
var b int64 = a // compilation error: cannot use a as int64

var b int64 = int64(a) // explicit conversion is required

What Happens When a Value Exceeds the Range?

If a number exceeds the maximum value of its type, an overflow occurs. The value wraps around to the minimum value.

var x int32 = 2147483647 // maximum int32 value
x++

fmt.Println(x) // -2147483648 — wrapped to the minimum value

Go does not produce a runtime error for integer overflow. This must be handled by the developer when necessary.

Which Type Should You Use?

Use int by Default

This is the idiomatic, commonly accepted choice in Go. Use int for counters, indexes, collection lengths, and general-purpose calculations.

for i := 0; i < len(slice); i++ {
	// ...
}

count := 0 // int

The Go standard library commonly uses int. The len and cap functions return int, and slice and array indexes also use integer values.

Use int64 When...

1. Values can be very large

var fileSize int64      // a file may be larger than 2 GB
var unixTimestamp int64 // time since 1970
var population int64    // the world's population is greater than 2.1 billion

2. You are working with a database

SQL fields of type BIGINT are commonly mapped to int64. Identifiers are also often stored as int64.

type User struct {
	ID int64 // corresponds to BIGINT in the database
}

3. You are storing money in cents or another smallest currency unit

To avoid floating-point errors, monetary values can be stored as integers in the smallest currency unit.

var balance int64 // in kopecks: 100 kopecks = 1 ruble
                  // can store up to approximately 92 quadrillion kopecks

4. You need a guaranteed size on every platform

For example, when implementing a data exchange protocol used by another system.

Use int32 When...

1. You need to save memory in large arrays

If you have 100 million small integer values, int32 requires half as much memory as int64.

ids := make([]int32, 100_000_000) // 400 MB instead of 800 MB

2. You are serializing data into a fixed-size format

For example, a binary network protocol may explicitly require a four-byte integer.

3. You are working with external APIs

Many protocols, including Protocol Buffers and gRPC, distinguish between int32 and int64. If a .proto file declares an int32, the generated Go field will also use int32.

Converting Between Types

Go does not perform implicit conversions between numeric types. You must always convert values explicitly:

var a int = 100
var b int64 = int64(a)
var c int32 = int32(b)

Converting from a larger type to a smaller one can be dangerous:

var big int64 = 5_000_000_000 // does not fit into int32
var small int32 = int32(big)  // the value is truncated

fmt.Println(small) // 705032704 — incorrect original value

The conversion does not check whether the original value fits into the target type.

Comparisons Are Also Strictly Typed

Variables of different integer types cannot be compared directly:

var a int = 5
var b int32 = 5

fmt.Println(a == b) // compilation error: mismatched types int and int32

One of the values must first be converted:

fmt.Println(a == int(b)) // true

Practical Example: Working with Time

import "time"

t := time.Now()

// Unix timestamp: the number of seconds since 1970
sec := t.Unix()  // returns int64
fmt.Println(sec) // for example, 1714298400

// If this value is stored as int32, it will stop fitting around the year 2038.
// This is known as the Year 2038 problem.

Practical Example: File Size

import "os"

info, _ := os.Stat("video.mp4")
size := info.Size() // returns int64 because a file can be larger than 4 GB

if size > 1024*1024*1024 {
	fmt.Println("Large file")
}

If Size() returned int32, the library would not be able to correctly represent files larger than approximately 2 GB.

Summary

ScenarioRecommended type
Counters, indexes, lengths, and general tasksint by default
File sizes, timestamps, database IDs, and moneyint64
Large arrays of small numbers and binary protocolsint32
Guaranteed size regardless of the platformint32 or int64, never int

Main rule: when you are unsure, use int. It is idiomatic, efficient on modern systems, and sufficient for most tasks.