В Go объявление переменной имеет вид: var name type = expression
. Можно не указывать тип или оператор присваивания с выражением, но один из них должен присутствовать. Кроме того, существует краткая форма объявления переменной. Рассмотрим все эти варианты:
- Объявление без явного указания типа:
var name = expression
. - Длинное объявление с указанием типа:
var name type
иvar name type = expression
. - Короткая нотация:
name := expression
.
Правил, которые регламентировали бы использование той или иной формы, в Go нет. Можно исходить из личных предпочтений или придерживаться стиля, принятого в вашей компании.
Объявление без указания типа
Тип переменной можно опускать, если при объявлении происходит инициализация. Тогда тип переменной будет равен типу выражения. Если переменной присваивается число, то компилятор установит тип int
или float64
.
Опишем в таблице инициализирующие значения и типы, которые компилятор присваивает объявленным переменным:
Объявление переменной | Тип переменной |
---|---|
var i = 10 | int |
var f = 5.0 | float64 |
var s = "Hello, world!" | string |
var r = 'Щ' | rune (int32 ) |
var b = true | bool |
Множество переменных можно инициализировать через запятую или с помощью вызова функции, которая возвращает несколько значений.
Длинное объявление
Если при определении переменной указан только тип, ей будет присвоено нулевое значение этого типа. Если нужно создать несколько переменных одного типа, их можно перечислить через запятую.
Полная запись с указанием типа и начального значения, как правило, используется тогда, когда тип переменной должен отличаться от типа, который присваивается компилятором по умолчанию.
Можно не указывать var
перед каждой переменной, а объединять переменные в блоки var (...)
. Это удобно, когда нужно обозначить схожие по смыслу сущности.
Короткая нотация
Конструкция с ключевым словом var
используется не всегда. В Go есть форма объявления переменной в теле функции с инициализацией. Эту форму принято называть короткой нотацией. Ключевое слово var
и тип не указываются, а вместо символа = пишется :=.
По умолчанию тип переменной равен типу присваиваемого выражения. В случае числовых типов компилятор сам выбирает размерность типа. Это может быть неудобно, когда нужно, например, объявить короткой нотацией переменную типа int64
, а не int
. Аналогично и с uint
.
Проблему решает операция приведения типов:
Короткая нотация прекрасно работает со множественным объявлением. Но в этом случае хотя бы одна переменная в выражении должна быть новой. В противном случае возникнет ошибка компиляции:
Константы
Константа — это типизированное значение, которое вычисляется на этапе компиляции и известно компилятору. В отличие от переменной, значение константы не может быть изменено во время работы программы. Вы уже сталкивались с константами ранее — это строковые, булевы и числовые литералы.
Если в коде постоянно используется какое-то число или строка, можно присвоить это значение переменной, но тогда оно не будет защищено от случайного изменения. Для решения этой проблемы Go даёт возможность давать константам имена.
Именованные константы
Ключевое слово const
определяет именованную константу, при этом константе можно присвоить результат некоторого выражения. В одном объявлении const
можно определить несколько констант.
Именованные константы можно инициализировать выражениями, состоящими из констант или литералов следующих типов:
- числа;
- строки;
- символы (руны);
- булевы значения.
Именованные константы позволяют изменять значение только в одном месте кода. Например, в приведённом примере легко увеличить точность числа пи или изменить номер версии.
Нетипизированные константы
Именованные константы могут быть разного типа. Тип связан с хранимым значением:
Может показаться, что если опустить тип при объявлении константы, то компилятор выберет его сам — как в случае с короткой формой объявления переменных. Это так лишь отчасти. В случае с константами отсутствие явного указания типа имеет большее значение.
Например, если вы объявляете константу intConst
и присваиваете ей значение 5
, то получаете целочисленную константу с неопределённым типом (untyped int
). Конкретный тип значения этой константы ещё не определён и в разных контекстах будет интерпретироваться компилятором по-разному. Это позволяет ослабить типизацию для констант, не отказываясь от сильной типизации глобально.
Благодаря этому подходу будет работать следующий пример:
Если определить id
как переменную var id = 100
, то возникнут ошибки компиляции при определении переменных i
и f
.
Если бы константы, как и переменные в Go, всегда имели конкретный тип, то работать с ними было бы сложнее. Более того, Go позволяет смешивать числовые литералы разных типов (untyped int
, untyped float
), поэтому корректно следующее выражение:
Константы, как и переменные, можно группировать.
Если в группе у константы не указано значение, то оно равно значению предыдущей константы.
Результатом работы программы будет:
pi = 3.1415 e = 3.1415
name = John Doe fullName = John Doe
Типизированные константы
Если при объявлении вы указываете тип константы явным образом, она становится типизированной и подчиняется правилам сильной типизации Go. В этом случае вы работаете с константой как с неизменяемой переменной:
При компиляции этого примера возникнет ошибка cannot use flag (constant 128 of type uint8) as type int in variable declaration
, так как у константы flag
тип uint8
, а у переменной i
тип int
.
Ключевое слово iota
🔗 Where and When to use Iota in Go
Что, если в коде нужно реализовать перечисление (enum)? В Go для этого нет встроенной синтаксической конструкции или специального типа. Однако можно просто объявить ряд констант и работать с ними:
Зачастую в перечислении важна прежде всего возможность различить два элемента. Значения же этих элементов (в данном случае констант) играют второстепенную роль. Это значит, что необязательно использовать строковые константы — вполне подойдут целочисленные:
При таком перечислении вручную есть вероятность получить неожиданное поведение — например, если по ошибке присвоить двум константам в перечислении одинаковое целочисленное значение:
К тому же при таком подходе не очень удобно объявлять длинные перечисления.
Для удобного объявления и инициализации блоков констант в Go есть автоматический инкремент iota
. При объявлении каждого блока const
значение iota
равно 0 и увеличивается на 1 для каждого следующего элемента:
Данную конструкцию применяют не только для перечислений. Ключевое слово iota
можно также использовать в арифметических выражениях, чтобы быстро объявить ряд значений с прогрессией. Следует помнить, что iota
увеличивается на единицу для каждой строки, где указано имя константы, даже если той было присвоено конкретное значение.
Пользовательские типы в константах
Предположим, нужно определить константы для дней недели.
Если перечислить их так, то все константы будут иметь нетипизированный числовой тип и могут использоваться в любых выражениях, что может вносить путаницу: var i int = Monday + 1
. В подобных случаях стоит определить пользовательский тип и указать его при определении констант.
Программа выведет:
today = 7 tomorrow = 1
Литералы
В Go можно использовать различные представления строковых и числовых литералов. Проиллюстрируем на примере целого числа 1000
:
Любой из этих литералов может быть использован в выражениях и даст одно и то же значение.
📂 Go | Последнее изменение: 15.08.2024 14:55