Константы и iota
const — неизменяемые значения
const объявляет значение, которое нельзя изменить. Это не переменная — это имя для значения:
const Pi = 3.14159265358979
const MaxRetries = 3
const AppName = "Zumno"
Pi = 3.0 // ОШИБКА: cannot assign to PiКонстанты вычисляются при компиляции, а не в рантайме. Это важно — ты не можешь объявить константу, значение которой неизвестно до запуска программы:
const x = 42 // OK — известно при компиляции
const y = math.Sqrt(2) // ОШИБКА — функция вызывается в рантайме
var z = math.Sqrt(2) // OK — переменная может быть вычислена в рантаймеГрупповое объявление
const (
StatusOK = 200
StatusNotFound = 404
StatusError = 500
)Нетипизированные константы
В Go константы бывают двух видов:
const typed int = 42 // типизированная — всегда int
const untyped = 42 // нетипизированная — тип определяется контекстомНетипизированные константы гибкие — компилятор подбирает тип при использовании:
const x = 42
var a int = x // OK — x интерпретируется как int
var b float64 = x // OK — x интерпретируется как float64
var c byte = x // OK — x интерпретируется как byte (uint8)Типизированная константа так не может:
const x int = 42
var a int = x // OK
var b float64 = x // ОШИБКА: cannot use x (type int) as type float64Нетипизированные константы хранятся с произвольной точностью внутри компилятора. Поэтому math.Pi работает без потери точности при любом float-типе.
iota — автоматический счётчик
iota — специальный идентификатор внутри const блока. Начинается с 0 и увеличивается на 1 с каждой строкой:
const (
A = iota // 0
B = iota // 1
C = iota // 2
)Но обычно пишут короче — Go повторяет выражение:
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)Мощные паттерны с iota
Битовые флаги — 1 << iota
Классический паттерн для флагов прав доступа, конфигурации и т.д.:
const (
Read = 1 << iota // 1 << 0 = 1 = 0b001
Write // 1 << 1 = 2 = 0b010
Execute // 1 << 2 = 4 = 0b100
)Каждая константа — отдельный бит. Можно комбинировать через |:
perms := Read | Write // 3 = 0b011
perms |= Execute // 7 = 0b111 — добавить Execute
// Проверка:
if perms & Read != 0 { fmt.Println("читать можно") }
if perms & Execute != 0 { fmt.Println("запускать можно") }Пропуск значений через _
const (
_ = iota // 0 — пропускаем (0 часто означает "не задано")
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1 048 576
GB // 1 << 30 = 1 073 741 824
TB // 1 << 40
)Выражения с iota
iota можно использовать в любом константном выражении:
const (
Small = (iota + 1) * 10 // 10
Medium // 20
Large // 30
XLarge // 40
)Несколько const блоков — iota сбрасывается
const A = iota // 0 — новый блок, iota = 0
const (
X = iota // 0 — снова с нуля
Y // 1
Z // 2
)Константы vs переменные
const | var | |
|---|---|---|
| Изменяемость | ❌ нельзя | ✅ можно |
| Вычисление | при компиляции | при запуске |
| Где объявлять | пакет + функция | пакет + функция |
| Адрес памяти | нет (не хранится) | есть |
| iota | ✅ | ❌ |
Используй const для:
- Математических констант (
Pi,E) - Конфигурационных значений (
MaxRetries,Timeout) - Перечислений и флагов (через
iota) - Строковых констант (
AppVersion)
Используй var если значение может меняться или вычисляется в рантайме.
В следующем уроке разберём пакет fmt глубоко — все форматные глаголы, выравнивание, Stringer интерфейс.