Константы в Go
Значение константы не может быть изменено во время выполнения. После присваивания оно не может быть изменено. Значение может происходить только из:
- Литералов
- Других идентификаторов констант
- Константных выражений
- Преобразований типов, результатом которых являются константы
- iota
Константы могут быть только основных типов данных, не могут быть:
- Другими типами, кроме основных, такими как структуры, интерфейсы, срезы, массивы и т.д.
- Возвращаемыми значениями функций
Значение константы не может быть изменено, иначе код не скомпилируется.
Инициализация
Для объявления константы используется ключевое слово const. Константа должна быть инициализирована значением при объявлении, и тип константы можно опустить. Например:
const name string = "Jack" // литерал
const msg = "hello world" // литерал
const num = 1 // литерал
const numExpression = (1+2+3) / 2 % 100 + num // константное выражениеЕсли просто объявить без указания значения, код не скомпилируется:
const name stringКомпилятор выдаст ошибку:
missing init expr for nameДля объявления нескольких констант можно использовать () для повышения читаемости. Можно использовать несколько () для группировки:
const (
Count = 1
Name = "Jack"
)
const (
Size = 16
Len = 25
)В одной группе констант константы после уже присвоенной константы могут не получать значение — их значение по умолчанию равно значению предыдущей константы:
const (
A = 1
B // 1
C // 1
D // 1
E // 1
)iota
iota — встроенный идентификатор константы, обычно используется для представления безтипового целочисленного порядкового номера в объявлении константы, обычно используется в скобках.
const iota = 0Несколько примеров использования:
const (
Num = iota // 0
Num1 // 1
Num2 // 2
Num3 // 3
Num4 // 4
)Также можно написать так:
const (
Num = iota*2 // 0
Num1 // 2
Num2 // 4
Num3 // 6
Num4 // 8
)И ещё так:
const (
Num = iota << 2*3 + 1 // 1
Num1 // 13
Num2 // 25
Num3 = iota // 3
Num4 // 4
)Из приведённых примеров видно, что iota инкрементируется. Первое константное выражение с iota определяет шаблон, и последующие константы автоматически получают значения согласно изменению порядкового номера, пока не будет сброшено новым const. Этот порядковый номер — фактически относительный номер строки кода относительно начальной строки текущей группы. Пример:
const (
Num = iota<<2*3 + 1 // 1 первая строка
Num2 = iota<<2*3 + 1 // 13 вторая строка
_ // 25 третья строка
Num3 //37 четвёртая строка
Num4 = iota // 4 пятая строка
_ // 5 шестая строка
Num5 // 6 седьмая строка
)В примере используется анонимный идентификатор _ для занятия строки. Значение iota по сути — разница между строкой, где находится iota, и первой строкой текущей группы const. Разные группы const не влияют друг на друга.
Перечисления
В Go нет отдельного типа данных для перечислений, в отличие от других языков, где обычно есть enum. В Go перечисления реализуются через пользовательский тип + const + iota. Простой пример:
type Season uint8
const (
Spring Season = iota
Summer
Autumn
Winter
)Эти перечисления фактически являются числами. Go не поддерживает прямое преобразование в строки, но мы можем добавить метод к пользовательскому типу для возврата строкового представления, реализовав интерфейс Stringer:
func (s Season) String() string {
switch s {
case Spring:
return "spring"
case Summer:
return "summer"
case Autumn:
return "autumn"
case Winter:
return "winter"
}
return ""
}Таким образом реализуется простое перечисление. Также можно использовать официальный инструмент Stringer для автоматической генерации перечислений.
Однако у этого подхода есть недостатки:
Небезопасность типов: поскольку
Season— пользовательский тип, можно выполнить принудительное преобразование других чисел в этот тип:goSeason(6)Громоздкость: строковое представление нужно реализовывать вручную
Слабая выразительность: поскольку
constподдерживает только основные типы данных, значения перечислений могут быть представлены только строками и числами
Автору непонятно, почему перечисления не поддерживаются на уровне языка — это определённо было бы преимуществом.
