Avatar ·

Разница между := и = в Go: короткое объявление против присваивания

Всем привет! Я только начал изучать Go и запутался в операторах := и =. Вроде бы оба используются для работы с переменными, но в чём разница? Вот пример, который меня смутил: ```go package main import "fmt" func main() { name := "Анна" // это работает var age int = 25 // это тоже работает age = 30 // и это работает // name = "Борис" // это я тоже пробовал } ``` Когда я пишу name := "Анна" — всё ок. Но если я сначала объявляю переменную через var, а потом пытаюсь использовать := с той же переменной, компилятор ругается: "no new variables on left side of :=". Почему? Ещё я заметил, что := работает только внутри функций. Если я пишу так: ```go var version = "1.0" // глобально — норм // version := "1.0" // глобально — ошибка! ``` Почему так? И в каких случаях нужно использовать :=, а в каких — просто =? Я перечитал несколько туториалов, но всё равно путаюсь. Объясните, пожалуйста, на пальцах, с примерами, когда что применять. Заранее спасибо! <<>>

Короткое объявление (:=) vs присваивание (=)

Это один из самых частых вопросов у новичков в Go. Давайте разберёмся раз и навсегда. Главное отличие в том, что := — это объявление + инициализация новой переменной, а = — это присваивание значения уже существующей переменной.

Оператор := (короткое объявление)

Он делает три вещи одновременно:

  • Объявляет новую переменную
  • Выводит её тип из выражения справа
  • Присваивает значение

Пример:

name := "Анна"          // объявили string
count := 42            // объявили int
pi := 3.14             // объявили float64
isReady := true        // объявили bool

Это эквивалентно:

var name string = "Анна"
var count int = 42
// и так далее

Оператор = (присваивание)

Используется ТОЛЬКО для изменения значения уже существующей переменной:

var age int
age = 25   // присваиваем значение
age = 30   // меняем значение

Почему нельзя использовать := дважды с одной переменной?

Потому что переменная уже объявлена. Компилятор видит попытку повторного объявления и выдаёт ошибку. НО! Есть исключение — если слева есть хотя бы одна новая переменная, то := работает как "частичное переобъявление":

a := 1
b := 2
a, c := 3, 4   // a — переприсваивание, c — новая переменная. Работает!
// a, b := 5, 6   // ОШИБКА: обе переменные уже существуют

Где можно использовать :=?

  • Только внутри функций (в том числе методов)
  • Нельзя на уровне пакета (глобально)
  • Нельзя вне блоков кода
package main

// version := "1.0"   // ОШИБКА: короткое объявление вне функции
var version = "1.0"   // Правильно для глобальной области

func main() {
    x := 10            // OK — внутри функции
    if true {
        y := 20        // OK — внутри блока
        fmt.Println(y)
    }
}

Практические правила

Используйте := когда:

  • Объявляете новую переменную внутри функции
  • Хотите, чтобы тип вывелся автоматически
  • Пишете краткий код (например, в циклах for i := 0)

Используйте var + = когда:

  • Объявляете переменную на уровне пакета
  • Нужно явно указать тип (например, var x float64 вместо float32)
  • Объявляете переменную без начального значения (нулевое значение)
  • Хотите подчеркнуть, что переменная будет изменяться позже

Типичные ошибки новичков

// Ошибка 1: Использование := с существующей переменной
var x int
x := 5   // Ошибка: no new variables on left side of :=

// Ошибка 2: Использование = для объявления новой переменной
// x = 10   // Ошибка: x не объявлена

// Ошибка 3: Использование := вне функции
// global := "test"  // Ошибка

// Правильно:
var x int
x = 5

// Или сразу:
y := 5

Итоговая шпаргалка

  • := — "создай новую переменную и запиши туда значение"
  • = — "возьми существующую переменную и измени её значение"
  • := работает только внутри функций
  • := с одной стороны может переиспользовать старые переменные, если есть хотя бы одна новая

Со временем вы привыкнете. В Go принято использовать := для локальных переменных — это делает код короче и читаемее. А var оставляют для глобальных переменных и случаев, когда тип нужно указать явно.

<<>>

Дополнение: сравнение с другими языками и подводные камни

Если вы пришли из Python или JavaScript, может показаться, что := похож на обычное присваивание. Но в Go это именно объявление. Вот ключевые отличия:

  • Область видимости: := создаёт переменную в текущем блоке. Если внутри if или for написать x := 1, то снаружи этого блока x не будет видна.
  • Тень (shadowing): Можно случайно "затенить" внешнюю переменную:
func main() {
    x := 10
    if true {
        x := 20    // Новая переменная x, внешняя не меняется
        fmt.Println(x) // 20
    }
    fmt.Println(x) // 10 — внешняя осталась прежней
}

Подводный камень с switch и if: В Go можно объявлять переменные прямо в условии:

if err := doSomething(); err != nil {
    fmt.Println(err)  // err доступна только здесь
}
// fmt.Println(err)  // Ошибка: err не видна снаружи

Рекомендация: Для новичков — используйте var везде, пока не освоитесь. Это сделает код более явным. Затем постепенно переходите на := для локальных переменных. И помните: если компилятор ругается на := — скорее всего, переменная уже существует, и нужно просто =.