Skip to main content

В чём разница между int, int32 и int64?

Краткий ответ

ТипРазмерДиапазон значений
int32всегда 4 байта (32 бита)от -2 147 483 648 до 2 147 483 647
int64всегда 8 байт (64 бита)от -9.2·10¹⁸ до 9.2·10¹⁸
intзависит от платформы: 4 байта на 32-битных системах, 8 байт на 64-битныхсоответственно

Главные различия — размер в памяти, диапазон значений и переносимость между платформами.

Что значит «32 бита» и «64 бита»

Бит — это одна ячейка памяти, которая хранит 0 или 1. Чем больше битов мы выделяем под число, тем больше различных чисел оно может представлять.

Поскольку числа со знаком (могут быть отрицательными), один бит уходит на знак, и диапазон делится примерно пополам — половина под отрицательные, половина под положительные.

// int32: 4 миллиарда / 2 ≈ 2.1 миллиарда в каждую сторону
// int64: 1.8·10¹⁹ / 2 ≈ 9.2·10¹⁸ в каждую сторону

int32 и int64 — фиксированный размер

Эти типы гарантированно имеют свой размер на любой платформе. Это важно, когда:

var a int32 = 100
var b int64 = 100

fmt.Println(unsafe.Sizeof(a))  // 4 (всегда)
fmt.Println(unsafe.Sizeof(b))  // 8 (всегда)

unsafe.Sizeof — встроенная функция, возвращающая размер значения в байтах.

int — размер зависит от платформы

Тип int — это «удобный целочисленный тип по умолчанию», его размер выбирает компилятор в зависимости от того, на какую систему ты компилируешь программу:

var x int = 42
fmt.Println(unsafe.Sizeof(x))  // на твоей машине почти наверняка 8

⚠️ Несмотря на то, что на 64-битной системе int и int64 имеют одинаковый размер, это разные типы для компилятора. Между ними нельзя присваивать без явного преобразования:

var a int = 10
var b int64 = a    // ❌ ошибка компиляции: cannot use a (type int) as type int64

var b int64 = int64(a)  // ✅ нужно явное преобразование

Что произойдёт при выходе за диапазон

Если попытаться положить в число значение больше максимума, происходит переполнение (overflow) — число «оборачивается» через минимум.

var x int32 = 2147483647   // максимум для int32
x++
fmt.Println(x)             // -2147483648 — стало минимумом!

Go не выбрасывает ошибку при переполнении в рантайме (для производительности). Это нужно учитывать.

Какой тип выбирать на практике

По умолчанию используй int

Это идиоматичный (общепринятый) выбор для Go. Для счётчиков, индексов, размеров коллекций — всегда int.

for i := 0; i < len(slice); i++ {  // i и len() возвращают int
    ...
}

count := 0  // тоже int

Стандартная библиотека Go повсеместно использует int: len(), cap(), индексы слайсов и мап — всё int.

Используй int64, когда...

1. Числа могут быть очень большими

var fileSize int64       // размер файла может быть > 2 ГБ
var unixTimestamp int64  // время в наносекундах с 1970
var population int64     // население Земли > 2.1 млрд

2. Работаешь с базой данных

В SQL поля типа BIGINT маппятся на int64. ID часто хранят как int64:

type User struct {
    ID int64  // соответствует BIGINT в БД
}

3. Считаешь деньги в копейках/центах

Чтобы избежать ошибок с плавающей точкой, деньги хранят как целые числа в минимальной единице:

var balance int64  // в копейках. 100 копеек = 1 рубль
                   // позволяет хранить до ~92 квадриллионов копеек

4. Нужна гарантия размера на любой платформе

Например, для протокола обмена с другой системой.

Используй int32, когда...

1. Экономишь память в больших массивах

Если у тебя 100 миллионов чисел и они все маленькие — int32 занимает в 2 раза меньше памяти, чем int64.

ids := make([]int32, 100_000_000)  // 400 МБ вместо 800 МБ

2. Сериализация в форматы с фиксированным размером

Например, бинарные сетевые протоколы, где явно указано «здесь идёт 4-байтовое целое».

3. Работа с внешними API

Многие протоколы (Protocol Buffers, gRPC) различают int32 и int64. Если в .proto-файле написано int32, то и в Go должен быть int32.

Преобразования между типами

В Go нет неявных преобразований между числовыми типами — даже если они разной разрядности. Всегда нужно писать явно:

var a int = 100
var b int64 = int64(a)    // явное преобразование
var c int32 = int32(b)    // тоже явное

// Опасный случай — преобразование "сверху вниз"
var big int64 = 5_000_000_000      // не помещается в int32
var small int32 = int32(big)        // обрезается! значение испортится
fmt.Println(small)                  // 705032704 — мусор

Сравнение по типам — тоже строгое

Нельзя сравнивать переменные разных целочисленных типов напрямую:

var a int = 5
var b int32 = 5
fmt.Println(a == b)  // ❌ ошибка: mismatched types int and int32

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

Реальный пример: работа с временем

import "time"

t := time.Now()

// Unix timestamp — секунды с 1970 года
sec := t.Unix()             // возвращает int64
fmt.Println(sec)            // например, 1714298400

// Если попробовать положить в int32 — на ~2038 год значение перестанет помещаться
// (это известная "проблема 2038 года" в системах, где timestamp хранится как int32)

Реальный пример: размер файла

import "os"

info, _ := os.Stat("video.mp4")
size := info.Size()    // возвращает int64
                       // потому что файл может быть > 4 ГБ

if size > 1024*1024*1024 {
    fmt.Println("Большой файл")
}

Если бы Size() возвращал int32, библиотека не могла бы корректно обрабатывать файлы больше 2 ГБ.

Краткое резюме

СценарийЧто использовать
Счётчики, индексы, размеры, общие задачиint (по умолчанию)
Размеры файлов, timestamps, ID в БД, деньгиint64
Большие массивы маленьких чисел, бинарные протоколыint32
Гарантия размера независимо от платформыint32 или int64 (никогда int)

Главное правило: если не уверен — используй int. Это идиоматично, эффективно на современных машинах и достаточно для большинства задач.

Serzh AI Academy — В чём разница между int, int32 и int64?