Типы и переменные в Go для тех, кто пришёл с Python
Go требует объявлять типы переменных явно — и это ломает привычки питониста с первой строки. Разбираем систему типов Go на контрасте с Python: от объявления переменных до преобразования типов, с рабочими примерами и проверками на каждом шаге.

Что нужно до начала
Вам понадобится установленный Go версии 1.21 или новее. Проверьте в терминале:
go version
# Ожидаемый вывод: go version go1.21.x (или старше)
Если команда не найдена — установите Go с официального сайта. Редактор подойдёт любой, но VS Code с расширением Go заметно упростит жизнь: он подсвечивает ошибки типов до компиляции.
Создайте рабочую директорию и инициализируйте модуль:
mkdir go-types-lab && cd go-types-lab
go mod init go-types-lab
Все примеры ниже — файлы с функцией main, которые запускаются через go run имя_файла.go.
Шаг 1. Объявление переменных — три способа вместо одного
В Python вы просто пишете count = 10, и интерпретатор решает, что это int. В Go переменная привязана к типу навсегда: если объявлена как int, строку в неё не положить.
package main
import "fmt"
func main() {
// Способ 1: полное объявление с типом
var count int = 10
// Способ 2: тип выведен компилятором из значения
var name = "Gopher"
// Способ 3: короткое объявление (только внутри функций)
ratio := 3.14
fmt.Println(count, name, ratio)
}
Сохраните как step1.go и запустите:
go run step1.go
# Ожидаемый вывод: 10 Gopher 3.14
Проверка: если вывод совпал — переменные объявлены верно. Попробуйте добавить строку count = "hello" перед fmt.Println — компилятор откажет с ошибкой cannot use "hello" (untyped string constant) as int value. Это и есть статическая типизация в действии.
Когда какой способ
var x int— когда нужна переменная с нулевым значением без присваивания (дляintэто0, дляstring— пустая строка, дляbool—false).var x = значение— когда тип очевиден из значения и вы хотите подчеркнуть, что переменная пакетного уровня.x := значение— самый частый вариант внутри функций. Короче, читается легче.
Шаг 2. Базовые типы — карта соответствий с Python
В Python один целочисленный тип — int — произвольной длины. В Go целых типов больше десятка, и каждый занимает фиксированный объём памяти. Вот ключевые:
| Python | Go | Размер | Комментарий |
|---|---|---|---|
int | int | зависит от платформы (обычно 64 бит) | для большинства задач хватает |
int (малые числа) | int8, int16, int32, int64 | 1 / 2 / 4 / 8 байт | нужны, когда важен размер: протоколы, бинарные форматы |
float | float64 | 8 байт | float32 существует, но float64 — дефолт |
str | string | заголовок 16 байт + данные | неизменяемая последовательность байт (UTF-8) |
bool | bool | 1 байт | true / false (с маленькой буквы) |
bytes | []byte | заголовок слайса + данные | слайс байтов, изменяемый |
Сохраните и запустите:
package main
import "fmt"
func main() {
var age int = 30
var temperature float64 = 36.6
var greeting string = "Привет"
var active bool = true
var raw []byte = []byte{72, 101, 108, 108, 111}
fmt.Println(age, temperature, greeting, active, string(raw))
}
go run step2.go
# Ожидаемый вывод: 30 36.6 Привет true Hello
Проверка: string(raw) превращает слайс байтов в строку — аналог bytes.decode() в Python, но без указания кодировки: Go всегда работает с UTF-8.
Шаг 3. Нулевые значения — нет None, и это шок
Питонист привык к None как к универсальному «ничего». В Go у каждого типа есть нулевое значение (zero value), и оно конкретное:
int,float64→0string→""(пустая строка)bool→false- указатели, слайсы, map, каналы, интерфейсы →
nil
package main
import "fmt"
func main() {
var n int
var s string
var ok bool
var p *int // указатель на int
fmt.Println(n, s, ok, p)
// Вывод: 0 false <nil>
// Пустая строка между 0 и false — это и есть пустой string
}
Главное отличие: вы не можете присвоить nil переменной типа int или string. Если вам нужно различать «ноль» и «значение не задано», используйте указатель *int — он может быть nil.
В Python отсутствие значения — этоNone, один на всех. В Go отсутствие значения нужно моделировать явно: указателем, отдельным флагом или типом из пакетаdatabase/sqlвродеsql.NullString. Это непривычно, но избавляет от целого класса багов сNoneType has no attribute.
Шаг 4. Преобразование типов — ничего неявного
В Python 3 + 2.5 даст 5.5 — интерпретатор сам приведёт int к float. В Go такой код не скомпилируется.
package main
import "fmt"
func main() {
count := 3 // int
ratio := 2.5 // float64
// result := count + ratio // ошибка компиляции: mismatched types
result := float64(count) + ratio // явное преобразование
fmt.Println(result)
}
go run step4.go
# Ожидаемый вывод: 5.5
Преобразование между числовыми типами — синтаксис тип(значение). Между строкой и числом — через пакет strconv:
package main
import (
"fmt"
"strconv"
)
func main() {
s := "42"
// Аналог int("42") в Python
n, err := strconv.Atoi(s)
if err != nil {
fmt.Println("Ошибка:", err)
return
}
fmt.Println(n + 8) // 50
// Обратно: число → строка
back := strconv.Itoa(n)
fmt.Println(back) // "42"
}
Проверка: вывод — 50 и 42. Обратите внимание: strconv.Atoi возвращает два значения — результат и ошибку. Игнорировать ошибку через _ можно, но не стоит: если в строке окажется "abc", программа получит ноль и молча продолжит работу — баг, который в Python упал бы с ValueError.
1 Термин: zero value — значение, которым Go инициализирует переменную, если вы не задали своё. Для каждого типа оно своё и определено спецификацией языка. Аналога в Python нет: там неинициализированная переменная просто не существует.
Шаг 5. Составные типы — массивы, слайсы, map
Питонист работает со списками и словарями. В Go им соответствуют слайсы и map, но с жёстко заданными типами элементов.
package main
import "fmt"
func main() {
// Слайс строк — аналог list[str] в Python
languages := []string{"Python", "Go", "Rust"}
languages = append(languages, "Zig")
fmt.Println(languages) // [Python Go Rust Zig]
// Map — аналог dict[str, int]
scores := map[string]int{
"Alice": 90,
"Bob": 85,
}
scores["Carol"] = 95
fmt.Println(scores) // map[Alice:90 Bob:85 Carol:95]
// Доступ к отсутствующему ключу — не паника, а zero value
val, exists := scores["Dave"]
fmt.Println(val, exists) // 0 false
}
Проверка: exists == false сообщает, что ключа нет. В Python вы бы получили KeyError, а в Go — молчаливый ноль. Идиома val, ok := m[key] — ваш аналог dict.get().
Шаг 6. Пользовательские типы и структуры
В Python для группировки данных используют классы или dataclass. В Go — структуры:
package main
import "fmt"
// User — аналог @dataclass в Python
type User struct {
Name string
Email string
Age int
}
func main() {
u := User{
Name: "Алиса",
Email: "alice@example.com",
Age: 28,
}
fmt.Println(u.Name, u.Age) // Алиса 28
// Поля, которые не заданы, получают zero value
empty := User{}
fmt.Println(empty) // { 0}
}
Структура — это не класс: у неё нет наследования. Методы привязываются к типу снаружи, а не внутри определения. Это тема отдельного разбора.
Если не получилось
cannot use "hello" as int value— вы пытаетесь положить значение одного типа в переменную другого. Решение: используйте явное преобразование или объявите переменную правильного типа.declared and not used— Go не компилирует код с неиспользованными переменными. Удалите переменную или используйте её. В Python это допустимо, в Go — нет.undefined: fmt— забыли строкуimport "fmt". Если используете VS Code с расширением Go, импорты добавляются автоматически при сохранении.mixed types in arithmetic/mismatched types— складываетеintиfloat64без приведения. Оберните одно из значений:float64(n).strconv.Atoi: parsing "abc": invalid syntax— строка не содержит число. Всегда проверяйте второе возвращаемое значениеerr.
Что делать дальше
Вы освоили объявление переменных, базовые и составные типы, преобразования и нулевые значения. Следующий логичный шаг — интерфейсы: именно они заменяют в Go утиную типизацию Python, но делают это через явный контракт, а не через hasattr. Начните с раздела Interfaces в официальном Tour of Go. Параллельно попробуйте переписать небольшой Python-скрипт на Go — именно при переносе реального кода ограничения типизации перестают казаться помехой и начинают помогать.
Проверка грамотности: Орфография, пунктуация, стиль — с объяснением каждой правки
Спросить за 10 ₽Источники: The Go Programming Language Specification — Types, A Tour of Go — Basic types
Частые вопросы
Можно ли менять тип переменной после объявления, как в Python?
Почему Go не приводит int к float64 автоматически?
Как передать None в функцию, которая ждёт string?
Чем слайс отличается от массива в Go?
А если у меня Go другой версии — примеры сработают?
Почему Go ругается на неиспользованные переменные? В Python это нормально.
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.