В чем разница между операторами := и = в Go? Объясните с примерами
Краткий ответ
:= — это короткая форма объявления и одновременно инициализации переменной.
= — это просто присваивание значения уже существующей переменной.
Главное правило: := можно использовать только если хотя бы одна переменная слева является новой.
Подробное объяснение
В Go есть два принципиально разных действия с переменными:
- Объявление (declaration) — создание переменной с указанием типа
- Присваивание (assignment) — запись значения в уже объявленную переменную
Оператор := делает сразу оба действия. Он объявляет переменную и присваивает ей значение. Тип определяется автоматически из выражения справа:
// Эквивалентные записи:
var x int = 10
var x = 10 // тип выводится автоматически
x := 10 // короткая форма — только внутри функций!
Главные отличия
| Оператор | Действие | Где использовать |
|---|---|---|
:= | Объявление + присваивание | Только внутри функций (включая методы) |
= | Только присваивание | Везде: функции, пакет, методы |
Правильные и неправильные примеры
// ✅ Правильно: объявляем новую переменную
x := 10
// ✅ Правильно: присваиваем значение существующей
x = 20
// ❌ Ошибка: x уже объявлена, нет новых переменных
x := 30
// ✅ Правильно: хотя бы одна переменная новая
x, y := 40, "hello" // y — новая, x — существующая
// ✅ Правильно: переиспользуем переменную в цикле
for i := 0; i < 5; i++ {
// i объявляется один раз, потом только присваивается
}
// ❌ Ошибка: := на уровне пакета
package main
version := "1.0" // нельзя! Используйте var version = "1.0"
Почему так сделано?
:= существует для удобства — чтобы не писать var каждый раз.
Но Go строг к объявлению переменных: вы не можете объявить одну и ту же переменную дважды в одной области видимости.
Поэтому компилятор проверяет, что слева от := есть хотя бы одна новая переменная.
Это защищает от случайного затирания значений.
Когда что использовать?
- Используйте := для локальных переменных внутри функций, особенно когда тип очевиден
- Используйте = для изменения значения уже существующей переменной
- Используйте var на уровне пакета, для глобальных переменных, или когда нужно явно указать тип
Типичная ошибка новичка
func main() {
var count int
count := 5 // ❌ Ошибка: count уже объявлен
// Правильно:
count = 5
// Или если нужно объявить сразу:
// count := 5 (без предварительного var)
}
Запомните: := — это "объявить и присвоить", = — это "присвоить существующей".
Как только переменная объявлена, используйте только =.
Дополнительный взгляд: область видимости и теневая переменная
Есть ещё один важный нюанс, который часто путает новичков. Оператор := создаёт новую переменную в текущей области видимости, даже если переменная с таким же именем существует во внешней области:
func main() {
name := "Alice"
{
name := "Bob" // Это НОВАЯ переменная, она "затеняет" внешнюю
fmt.Println(name) // Bob
}
fmt.Println(name) // Alice — внешняя не изменилась
}
С оператором = такого не произойдёт — он изменит именно ту переменную, которая доступна в текущей области:
func main() {
name := "Alice"
{
name = "Bob" // Изменяем ту же самую переменную
fmt.Println(name) // Bob
}
fmt.Println(name) // Bob — значение изменилось
}
Это поведение называется "shadowing" (затенение). Оно часто становится причиной багов, когда вы думаете, что изменяете переменную, а на самом деле создаёте новую. Совет: будьте внимательны с := внутри блоков if, for и других конструкций, создающих новую область видимости.
Если сомневаетесь — используйте var и = явно. Это немного длиннее, но безопаснее для понимания кода.