Константы и iota в Go: короткое руководство
Go позволяет объявлять типизированные и нетипизированные константы, а встроенный счётчик iota генерирует последовательности без магических чисел. Разбираем синтаксис, правила типизации и приёмы, которые экономят строки кода.

Что нужно до начала
Примеры проверены на Go 1.22. Подойдёт любая версия от 1.18 и выше — поведение констант и iota не менялось с ранних релизов языка. Достаточно установленного компилятора (go version должен отвечать) и любого текстового редактора.
Объявление констант
Константа в Go — значение, вычисленное на этапе компиляции. В отличие от переменной, оно не занимает адресуемую память, и взять его указатель нельзя. Объявляется ключевым словом const.
Одиночное объявление
const pi = 3.14159265358979323846
const greeting string = "Привет" // с явным типом
Если тип не указан, константа остаётся нетипизированной — и это не мелочь, а важная особенность Go.
Блочное объявление
const (
maxRetries = 5
timeout = 30 // секунды
baseURL = "https://api.example.com"
)
Блок const() группирует связанные значения и — что важнее — запускает механизм iota.
Типизированные и нетипизированные константы
Это различие часто путает тех, кто приходит из C или Java. Нетипизированная константа хранит значение с произвольной точностью и свободно подставляется в выражения разных типов. Типизированная ведёт себя как переменная соответствующего типа: автоматического приведения не будет.
const untyped = 100 // нетипизированная целочисленная
const typed int64 = 100 // типизированная int64
var f float64 = untyped // OK — нетипизированная подстраивается
// var f2 float64 = typed // ошибка компиляции: cannot use typed (int64) as float64
Проверка: раскомментируйте последнюю строку — компилятор выдаст ошибку. Это и есть разница.
Нетипизированные константы в Go — не «любой тип». Это значения, которые ещё не привязаны к конкретному типу и поэтому принимают тип контекста, в который попадают. Пока контекста нет, компилятор хранит их с повышенной точностью — для целых чисел это минимум 256 бит.
Практическое следствие: нетипизированная константа может хранить число, которое не влезает ни в один встроенный тип, — пока вы не пытаетесь присвоить её переменной.
const huge = 1 << 200 // компилируется
// var x int = huge // ошибка: переполнение
iota — встроенный счётчик
iota — целочисленный счётчик, который сбрасывается в 0 в каждом новом блоке const и увеличивается на 1 с каждой строкой спецификации. Это единственный способ в Go автоматически генерировать последовательности констант без повторения значений вручную.
Простейший пример: перечисление
type Weekday int
const (
Sunday Weekday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
Строки без явного выражения наследуют выражение предыдущей строки, подставляя новое значение iota. Поэтому Monday получает iota = 1, а не повторяет 0.
Пропуск нулевого значения
Частый приём — назначить нулю роль «неизвестного» значения, чтобы случайно необъявленная переменная не совпала с валидным состоянием:
type Role int
const (
_ Role = iota // 0 пропущен
Admin // 1
Editor // 2
Viewer // 3
)
Проверка: fmt.Println(Admin, Editor, Viewer) выведет 1 2 3.
Битовые флаги
Классическое применение — набор прав доступа, где каждое значение занимает отдельный бит:
type Permission uint
const (
Read Permission = 1 << iota // 1
Write // 2
Execute // 4
)
// Комбинирование флагов
const ReadWrite = Read | Write // 3
Выражение 1 << iota наследуется каждой следующей строкой, поэтому Write получает 1 << 1, а Execute — 1 << 2.
Единицы измерения
type ByteSize uint64
const (
_ ByteSize = iota // пропускаем 0
KB ByteSize = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20
GB // 1 << 30
TB // 1 << 40
)
Проверка: fmt.Println(KB, MB, GB, TB) → 1024 1048576 1073741824 1099511627776.
Правила iota, которые стоит запомнить
iotaсбрасывается в 0 в каждом отдельном блокеconst().- Счётчик увеличивается на 1 с каждой строкой спецификации, а не с каждым идентификатором. Если в одной строке два имени через запятую — оба получат одно значение
iota. - Пустая строка или комментарий не увеличивают
iota— увеличивает только строка с объявлением константы. - Выражение с
iotaможет быть любым: арифметика, сдвиги, вызовunsafe.Sizeof— всё, что вычисляется при компиляции.
Сравнение подходов к «перечислениям» в Go
В Go нет ключевого слова enum. Вот три способа, которыми разработчики решают ту же задачу:
| Подход | Плюс | Минус |
|---|---|---|
const + iota с кастомным типом | Проверка типов при компиляции, компактный синтаксис | Нет защиты от произвольного приведения: Role(42) компилируется без ошибок |
| Строковые константы | Читаемы в логах и JSON без дополнительного маршаллера | Опечатка в строке не ловится компилятором; занимают больше памяти |
Пакет-генератор stringer | Автоматический String() для iota-перечислений | Требует кодогенерации (go generate); добавление новой константы без перегенерации ломает вывод |
Самый распространённый путь — const + iota плюс stringer для отладочного вывода.
Если не получилось
cannot use ... as type ... in assignment— вы присвоили типизированную константу переменной другого типа. Решение: уберите тип из объявления константы или выполните явное приведение.constant ... overflows int— нетипизированная константа слишком велика для целевого типа. Решение: используйтеuint64или пересмотрите выражение.- Все константы в блоке получили одно и то же значение — скорее всего, первая строка не содержит
iota, и остальные наследуют фиксированное выражение. Убедитесь, что хотя бы первая строка явно используетiota. iotaначинается не с того числа — помните, чтоiotaсчитает строки от нуля внутри блока. Если вы пропустили строку через_, следующая константа получитiota= 1, а не 0.
iota — встроенный предобъявленный идентификатор Go (не ключевое слово), представляющий целочисленный индекс текущей строки спецификации внутри блока const. Имя заимствовано из APL, где iota генерировала последовательность целых чисел.
Что дальше
Константы и iota — один из тех механизмов Go, которые выглядят тривиально, пока не столкнёшься с нетипизированной арифметикой или неожиданным наследованием выражений. Следующий шаг — добавить к своим iota-перечислениям метод String() через утилиту stringer (устанавливается командой go install golang.org/x/tools/cmd/stringer@latest) и настроить go generate. Также полезно посмотреть раздел спецификации о константных выражениях — там описана точная семантика нетипизированных значений и правила их приведения.
Субтитры и таймкоды: Расшифровка речи и субтитры по правилам читаемости: 42 знака в строке, две строки, минимум секунда на реплику.
Спросить за 40 ₽Источники: The Go Programming Language Specification — Constants, Effective Go — Constants
Частые вопросы
Можно ли использовать iota вне блока const?
Сбрасывается ли iota между разными блоками const в одном файле?
Как получить строковое представление константы, объявленной через iota?
Что будет, если я добавлю новую константу в середину iota-блока?
А если у меня другая версия Go — iota работает так же?
Можно ли сериализовать iota-константы в JSON как строки, а не числа?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.