Урок курса

Переменные, константы и базовые типы

Golang с нуля

В предыдущих уроках вы уже написали программу, которая компилируется и запускается. Теперь разберёмся, как Go работает с данными — как объявить переменную, задать ей тип и значение, и почему компилятор не даст вам сделать это «не так».

var и := — объявление переменных и ограничение области видимости :=

У var три рабочие формы, и между ними есть реальная разница.

var x int — объявляет переменную типа int без начального значения. Go сразу присваивает ей нулевое значение, в данном случае 0. Никакой «неинициализированной памяти» здесь нет: компилятор гарантирует, что переменная готова к использованию.

var x int = 42 — тип и значение указаны явно. Это бывает полезно, когда вы хотите зафиксировать тип, а значение правой части могло бы подойти и для другого.

var x = 42 — тип выводится из значения. Компилятор видит целочисленный литерал 42 и делает x типом int.

Теперь :=. Это сокращённая форма для объявления и инициализации в одном выражении:

package main

import "fmt"

func main() {
    x := 42
    fmt.Println(x) // 42
}

Тип x здесь int — вывелся из 42. Запись := короче, и в теле функций она встречается чаще всего.

Главное ограничение: := работает только внутри функции. Попробуйте вынести его на уровень пакета:

package main

x := 42 // вне функции

func main() {}

Компилятор ответит:

syntax error: non-declaration statement outside function body

Это не предупреждение — программа не скомпилируется. На уровне пакета переменные объявляются только через var. Разграничение простое: var — везде, := — только внутри func.

Ещё один момент про :=: если в левой части несколько имён, хотя бы одно из них должно быть новым в текущей области видимости. Иначе компилятор снова откажет — повторное объявление уже существующей переменной через := в той же области недопустимо.

const, базовые типы int/float64/bool/string и их нулевые значения

const объявляет именованную константу — значение, которое фиксируется на этапе компиляции и не может измениться в процессе выполнения программы.

const Pi = 3.14
const MaxItems int = 100

Эти две формы принципиально различаются. MaxItemsтипизированная константа: у неё зафиксирован тип int, и в любом контексте она ведёт себя именно как int. Piнетипизированная числовая константа: у неё нет конкретного типа при объявлении. Компилятор хранит её как константу вида «floating-point constant» с высокой точностью, а конкретный тип (float64, float32 или другой) она получит только тогда, когда используется в выражении, которое требует определённого типа. Если контекст не задан — применяется тип по умолчанию для данного вида константы (float64 для вещественных).

Попытка переприсвоить константу после объявления немедленно даёт ошибку компиляции: cannot assign to Pi. const допустим и внутри функции, и на уровне пакета.

Теперь о четырёх базовых типах, с которыми вы будете работать прямо сейчас:

  • int — целое число. Нулевое значение: 0.
  • float64 — число с плавающей точкой двойной точности. Нулевое значение: 0.
  • bool — логический тип. Нулевое значение: false.
  • string — строка. Нулевое значение: пустая строка "".

Каждый раз, когда вы пишете var без инициализатора, Go присваивает именно это значение. Посмотрите сами:

package main

import "fmt"

func main() {
    var i int
    var f float64
    var b bool
    var s string

    fmt.Println(i, f, b, s)
}

Вывод:

0 0 false 

Последний элемент — пустая строка, поэтому после false видно только пробел и конец строки. Нулевые значения — не случайный выбор: они семантически нейтральны для каждого типа и предсказуемы. В Go никогда не бывает ситуации, когда переменная «содержит мусор».

Явное преобразование типов: int↔float64 и отбрасывание дробной части

Go не выполняет числовые преобразования автоматически. Если у вас есть int и нужен float64 — вы должны сказать об этом явно. Синтаксис: TargetType(value).

package main

import "fmt"

func main() {
    i := 7
    f := float64(i)
    fmt.Println(f) // 7

    g := 3.9
    n := int(g)
    fmt.Println(n) // 3
}

Первое преобразование — int в float64 — прямолинейное: 7 становится 7 с плавающей точкой.

Второе интереснее. int(3.9) даёт 3, а не 4. Go отбрасывает дробную часть — это не округление, это усечение в сторону нуля. int(3.1), int(3.5) и int(3.9) дают одинаковый результат: 3.

Что будет, если попробовать обойтись без преобразования?

var i int = 5
var f float64 = i // ошибка компиляции
cannot use i (variable of type int) as type float64 in variable declaration

Компилятор отказывает даже в случае, когда значение «очевидно» совместимо. Это не ограничение — это защита: неявные преобразования между числовыми типами исторически порождают труднозаметные ошибки, и Go выбирает явность.

Синтаксис TargetType(value) работает для любых числовых типов, доступных в этом уроке. Результат всегда можно проверить через fmt.Println — именно так стоит делать, когда поведение усечения неочевидно.

Попробуйте решить

Какое значение выведет следующий код?

package main

import "fmt"

func main() {
    var s string
    var n int
    var f float64
    var b bool
    fmt.Println(s, n, f, b)
}

Продолжить с проверкой и прогрессом

Откройте интерактивный раннер с заданиями урока.

Перейти к интерактивному уроку