В языке программирования Go правильный выбор типов данных один из ключевых факторов, влияющих на производительность, потребление памяти и отсутствие скрытых ошибок. Особенно это касается целых чисел, которые используются практически в каждой программе.
Давайте разберёмся, какие целочисленные типы предлагает Go, в чём их различия и как их использовать с умом.

Знаковые и беззнаковые числа

Go чётко разделяет целые числа на знаковые (могут быть отрицательными) и беззнаковые (только неотрицательные).
Знаковые типы (signed):
  • int8 — 8 бит, диапазон: от -128 до +127
  • int16 — 16 бит, от -32 768 до +32 767
  • int32 — 32 бита, от -2 147 483 648 до +2 147 483 647
  • int64 — 64 бита, от -9 223 372 036 854 775 808 до +9 223 372 036 854 775 807
Беззнаковые типы (unsigned):
  • uint8 — 8 бит, диапазон: 0–255
  • uint16 — 16 бит, 0–65 535
  • uint32 — 32 бита, 0–4 294 967 295
  • uint64 — 64 бита, 0–18 446 744 073 709 551 615
Кроме фиксированных по размеру типов, в Go существуют ещё три особенных:
  • int — "обычный" знаковый целый (32 или 64 бита в зависимости от платформы)
  • uint — беззнаковый аналог
  • uintptr — беззнаковый тип, достаточный для хранения адреса указателя (его размер тоже зависит от платформы)

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

Выбор типа влияет на три важных аспекта: расход памяти, скорость работы и безопасность кода. Вот практические рекомендации:

Экономим память

Если значения гарантированно маленькие, то берите минимально достаточный тип.
Примеры:
  • возраст человека -> uint8 (хватит с запасом)
  • количество байтов в файле -> uint32 или uint64
  • счётчик до нескольких тысяч -> uint16 или int32

Согласованность с внешними системами

При работе с протоколами, бинарными файлами, базами данных или C-библиотеками используйте точно тот размер, который ожидает другая сторона (часто это int32 / uint32 / int64).

Максимальная производительность на 64-битных системах

На современных 64-битных процессорах операции с int и uint обычно быстрее, чем с int8/int16, потому что они соответствуют естественному размеру машинного слова и лучше выравниваются в памяти.

Полезные правила и типичные ошибки

Переполнение

Go не проверяет переполнение автоматически (в отличие от некоторых других языков).
  • uint8(255) + 1 -> получите 0
  • int8(-128) - 1 → получите +127

Строгая типизация

Нельзя просто сложить int32 и int64, компилятор потребует явного приведения типов:

Значение по умолчанию

Любая неинициализированная целочисленная переменная получает значение 0 — это удобно и предсказуемо. Более подробно мы это рассматривали в этой статье.

Итог

Хорошее понимание целочисленных типов в Go помогает писать более быстрый, экономичный и надёжный код. Главное — всегда задавать себе три вопроса:
  1. Каков реальный диапазон значений?
  2. Нужно ли отрицательное значение?
  3. Важна ли максимальная скорость на моей целевой платформе?
Ответив на них, вы почти всегда выберете оптимальный тип.