Переменные и типы данных
Учимся хранить информацию в программе: числа, текст, логические значения и многое другое
В прошлом уроке мы написали первую программу — «Hello, World!» — и разобрались, как Go-код превращается в работающее приложение. Но та программа просто выводила текст и завершалась. Настоящие программы работают с данными: считают цены, хранят имена пользователей, сравнивают числа. Чтобы работать с данными, нужно уметь их где-то хранить. Для этого в программировании существуют переменные. Представьте коробку с наклейкой: на наклейке написано имя (название переменной), а внутри лежит значение (число, текст или что-то другое). Сегодня мы научимся создавать такие коробки, узнаем, какие бывают типы данных в Go, и напишем программу-калькулятор площади комнаты.
📦 Что такое переменная
Переменная — это именованное место в памяти компьютера, где хранится какое-то значение. Когда вы создаёте переменную, компьютер выделяет кусочек оперативной памяти и запоминает: «вот здесь лежит значение, а обращаться к нему нужно по такому-то имени».
Аналогия простая. Представьте складское помещение с полками. На каждой полке лежит что-то одно: коробка с яблоками, коробка с гвоздями, коробка с книгами. У каждой полки есть номер и подпись, чтобы кладовщик мог быстро найти нужное. Переменная — это такая подписанная полка. Имя переменной — это подпись, а значение — это то, что лежит на полке.
В Go есть несколько способов создать переменную. Давайте разберём каждый из них.
📝 Объявление переменной через var
Самый классический способ — использовать ключевое слово var. Синтаксис такой: пишем var, затем имя переменной, затем её тип, и (по желанию) присваиваем начальное значение.
package main
import "fmt"
func main() {
var name string = "Алексей"
var age int = 25
var height float64 = 1.78
var isStudent bool = true
fmt.Println("Имя:", name)
fmt.Println("Возраст:", age)
fmt.Println("Рост:", height)
fmt.Println("Студент:", isStudent)
}
Разберём каждую строку:
var name string = "Алексей"— создаём переменнуюnameтипаstring(текст) со значением «Алексей»var age int = 25— переменнаяageтипаint(целое число) со значением 25var height float64 = 1.78— переменнаяheightтипаfloat64(дробное число) со значением 1.78var isStudent bool = true— переменнаяisStudentтипаbool(истина/ложь) со значением true
Go — умный язык. Если вы сразу присваиваете значение, можно не указывать тип — Go сам его определит. Это называется вывод типа (type inference):
var name = "Алексей" // Go понимает: строка → тип string
var age = 25 // Go понимает: целое число → тип int
var height = 1.78 // Go понимает: дробное число → тип float64
var isStudent = true // Go понимает: логическое значение → тип bool
Можно также объявить переменную без начального значения. В этом случае тип указывать обязательно — иначе Go не поймёт, что за переменную вы хотите:
var score int // объявили переменную, но пока ничего не положили
score = 100 // теперь положили значение
Если нужно объявить несколько переменных разом, можно использовать блок var с круглыми скобками — так код выглядит чище:
var (
firstName string = "Мария"
lastName string = "Иванова"
age int = 30
)
⚡ Короткое объявление через :=
В Go есть более короткий и удобный способ объявить переменную — оператор :=. Его называют «коротким объявлением» (short variable declaration). Вместо var name string = "Алексей" можно просто написать:
name := "Алексей"
age := 25
height := 1.78
isStudent := true
Оператор := одновременно объявляет переменную и присваивает ей значение. Go автоматически определяет тип по правой части. Это самый популярный способ объявления переменных в Go — вы будете видеть его в коде постоянно.
💡 Важное правило: оператор := можно использовать только внутри функций. На уровне пакета (вне функций) — только var. Если вы попробуете написать name := "Алексей" вне функции main, компилятор выдаст ошибку.
Ещё один нюанс: := создаёт новую переменную. Если переменная уже существует, используйте обычный = для присвоения нового значения:
age := 25 // создаём переменную age
age = 26 // меняем значение (переменная уже существует)
// age := 30 — ОШИБКА! переменная age уже объявлена
Когда использовать var, а когда :=? Простое правило: если вы сразу знаете значение переменной — используйте :=. Если хотите объявить переменную без значения (чтобы присвоить его позже) — используйте var.
🔒 Константы — значения, которые не меняются
Иногда вам нужно сохранить значение, которое никогда не должно меняться. Например, число Пи всегда равно 3.14159..., количество месяцев в году всегда 12, а скорость света — 299 792 458 м/с. Для таких значений в Go есть константы.
Константы объявляются через ключевое слово const:
const pi = 3.14159
const maxStudents = 30
const courseName = "Основы Go"
Если попытаетесь изменить константу, Go выдаст ошибку при компиляции:
const pi = 3.14159
pi = 3.14 // ОШИБКА: cannot assign to pi (constant)
Как и с var, несколько констант можно объединить в блок:
const (
pi = 3.14159
maxRetries = 5
appName = "MyApp"
)
💡 Подсказка: константы в Go — это не просто «переменные, которые нельзя менять». Они вычисляются во время компиляции, а не во время выполнения программы. Это значит, что константами могут быть только простые значения: числа, строки, логические значения. Нельзя, например, сделать константой результат вызова функции.
🧱 Базовые типы данных
В Go каждая переменная имеет тип. Тип определяет, какие данные можно хранить в переменной и какие операции с ней допустимы. Нельзя, например, сложить число с текстом — Go не позволит. Это называется статическая типизация, и это одно из главных преимуществ Go: многие ошибки обнаруживаются ещё до запуска программы.
Разберём четыре базовых типа, с которыми вы будете работать чаще всего.
int — целые числа
Тип int хранит целые числа: положительные, отрицательные и ноль. Это числа без дробной части: 1, 42, -10, 0, 1000000. Используется для подсчёта чего-либо, индексов, возраста, количества и других целочисленных значений.
count := 10
temperature := -5
year := 2026
fmt.Println(count + year) // 2036
fmt.Println(temperature * 2) // -10
float64 — дробные числа
Тип float64 хранит числа с дробной частью (числа с плавающей точкой): 3.14, 0.5, -2.7, 100.0. Число 64 в названии означает, что для хранения используется 64 бита памяти — это обеспечивает высокую точность. Используется для цен, расстояний, координат, научных расчётов.
price := 99.99
pi := 3.14159
weight := 72.5
fmt.Println(price * 2) // 199.98
fmt.Println(pi * 10) // 31.4159
string — текст (строки)
Тип string хранит текст — последовательность символов. Строки всегда записываются в двойных кавычках. Это могут быть имена, сообщения, адреса, любой текст. Строки можно складывать (конкатенировать) — при этом они просто склеиваются.
firstName := "Иван"
lastName := "Петров"
fullName := firstName + " " + lastName
fmt.Println(fullName) // Иван Петров
fmt.Println("Привет, " + firstName + "!") // Привет, Иван!
bool — логический тип (да/нет)
Тип bool хранит только два значения: true (истина) или false (ложь). Это самый простой тип данных, но невероятно важный. Он используется для условий: «пользователь авторизован?», «заказ оплачен?», «число больше нуля?».
isOnline := true
hasAccess := false
fmt.Println(isOnline) // true
fmt.Println(hasAccess) // false
fmt.Println(10 > 5) // true (результат сравнения — тоже bool)
fmt.Println(3 == 7) // false
🎯 Нулевые значения — фишка Go
Вот одна из вещей, которая делает Go особенным и отличает его от многих других языков. В Go каждая переменная, которой не присвоено значение, автоматически получает так называемое нулевое значение (zero value). Переменная никогда не бывает «пустой» или «неопределённой» — у неё всегда есть значение.
Вот какие нулевые значения получают разные типы:
int→ 0 (ноль)float64→ 0.0 (ноль с точкой)string→ "" (пустая строка)bool→ false (ложь)
Давайте убедимся в этом на практике:
package main
import "fmt"
func main() {
var number int
var decimal float64
var text string
var flag bool
fmt.Println("int:", number) // int: 0
fmt.Println("float64:", decimal) // float64: 0
fmt.Println("string:", text) // string:
fmt.Println("bool:", flag) // bool: false
}
Мы объявили четыре переменные через var, но не присвоили им никаких значений. Запустили программу — и всё работает, никаких ошибок. Каждая переменная получила своё нулевое значение.
Почему это важно? Во многих языках программирования (например, в C или C++) неинициализированная переменная содержит «мусор» — случайные данные, которые остались в памяти от предыдущих программ. Это может приводить к непредсказуемым ошибкам. В Go такая ситуация невозможна: каждая переменная гарантированно имеет осмысленное начальное значение.
💡 Запомните: в Go нет понятия «неинициализированная переменная». Если вы объявили переменную и не задали ей значение — она не пустая и не сломанная. Она содержит нулевое значение своего типа. Это важный принцип дизайна Go, который делает программы безопаснее и предсказуемее.
🔄 Явное приведение типов
В Go нельзя просто так смешивать разные типы данных. Например, нельзя сложить int и float64 напрямую — даже если математически это кажется логичным. Go строг к типам, и это защищает вас от скрытых ошибок.
a := 10 // int
b := 3.5 // float64
// c := a + b — ОШИБКА! Нельзя сложить int и float64
Чтобы выполнить такую операцию, нужно явно преобразовать один тип в другой. В Go для этого используется синтаксис тип(значение):
a := 10
b := 3.5
c := float64(a) + b // Преобразовали a из int в float64
fmt.Println(c) // 13.5
Можно и наоборот — преобразовать float64 в int. Но будьте внимательны: дробная часть просто отбрасывается (не округляется!):
price := 99.99
rounded := int(price)
fmt.Println(rounded) // 99 (дробная часть .99 потеряна!)
Ещё один частый пример — преобразование между числами и строками. Но тут всё не так просто. Нельзя написать string(65) и получить «65» — Go не так работает. Вместо этого string(65) вернёт символ с кодом 65, а это буква «A».
Для превращения числа в строку используется пакет strconv (мы подробнее разберём его в следующих уроках) или функция fmt.Sprintf:
package main
import "fmt"
func main() {
age := 25
message := fmt.Sprintf("Мне %d лет", age)
fmt.Println(message) // Мне 25 лет
}
Давайте посмотрим на более полный пример приведения типов:
package main
import "fmt"
func main() {
// int → float64
whole := 42
decimal := float64(whole)
fmt.Println(decimal) // 42
// float64 → int (дробная часть отбрасывается!)
pi := 3.99
truncated := int(pi)
fmt.Println(truncated) // 3
// int → другой числовой тип
big := 1000
small := int8(big) // int8 хранит числа от -128 до 127
fmt.Println(small) // -24 (переполнение! будьте осторожны)
}
💡 Подсказка: Go требует явного приведения типов, и это не недостаток, а преимущество. Когда вы видите float64(a) в коде, вы сразу понимаете: «здесь число преобразуется в дробное». Ничего не происходит «за кулисами», всё явно и прозрачно. Это делает Go-код легко читаемым.
🏷 Как правильно называть переменные
Хорошие имена переменных — это как понятные подписи на коробках. Если написать «X1» — непонятно, что внутри. Если написать «возрастПользователя» — сразу всё ясно. Вот несколько правил именования в Go:
- Имя начинается с буквы или подчёркивания
_ - Может содержать буквы, цифры и подчёркивания
- Регистр имеет значение:
ageиAge— это разные переменные - Нельзя использовать ключевые слова Go:
var,func,if,forи т.д. - В Go принят стиль camelCase:
firstName,maxRetries,isActive
// Хорошие имена — понятно, что хранится
userName := "Иван"
totalPrice := 1500.50
isLoggedIn := true
maxAttempts := 3
// Плохие имена — непонятно, что это
x := "Иван"
tp := 1500.50
f := true
m := 3
💡 Подсказка: в Go есть особое соглашение. Если имя переменной начинается с заглавной буквы (Age) — она доступна из других пакетов (экспортируемая). Если со строчной (age) — только внутри текущего пакета (неэкспортируемая). Пока не переживайте об этом — мы разберём пакеты позже. Просто начинайте имена со строчной буквы.
🚫 Неиспользуемые переменные — ошибка компиляции
В Go есть строгое правило: если вы объявили переменную, вы обязаны её использовать. Иначе программа просто не скомпилируется. Это может удивить новичков, но за этим стоит здравый смысл: неиспользуемая переменная — это либо ошибка (вы забыли что-то с ней сделать), либо мусор (переменная больше не нужна, но вы забыли её удалить).
package main
func main() {
name := "Алексей"
// Мы не используем name — ОШИБКА!
// name declared and not used
}
Чтобы код скомпилировался, нужно либо использовать переменную (напечатать, передать в функцию, выполнить операцию), либо удалить её. Если по какой-то причине вам нужно проигнорировать значение, используйте специальный идентификатор _ (подчёркивание):
_ = "это значение мы намеренно игнорируем"
Подчёркивание _ — это «чёрная дыра» в Go. Всё, что вы туда присваиваете, просто исчезает. Это полезно, когда функция возвращает несколько значений, а вам нужно только одно. Но об этом позже.
🛠 Практика: калькулятор площади комнаты
Давайте применим всё, что мы изучили, на практике. Напишем программу, которая вычисляет площадь комнаты и стоимость напольного покрытия.
Создайте новый файл area.go и введите следующий код:
package main
import "fmt"
func main() {
// Размеры комнаты (в метрах)
length := 5.5
width := 3.8
// Вычисляем площадь
area := length * width
// Цена за квадратный метр ламината (в рублях)
const pricePerSquareMeter = 850.0
// Общая стоимость
totalCost := area * pricePerSquareMeter
// Информация о комнате
roomName := "Гостиная"
needsRepair := true
// Выводим результат
fmt.Println("=== Калькулятор площади ===")
fmt.Println("Комната:", roomName)
fmt.Println("Длина:", length, "м")
fmt.Println("Ширина:", width, "м")
fmt.Println("Площадь:", area, "кв.м")
fmt.Println("Цена за кв.м:", pricePerSquareMeter, "руб.")
fmt.Println("Общая стоимость:", totalCost, "руб.")
fmt.Println("Нужен ремонт:", needsRepair)
}
Запустите программу:
go run area.go
Вы увидите результат:
=== Калькулятор площади ===
Комната: Гостиная
Длина: 5.5 м
Ширина: 3.8 м
Площадь: 20.9 кв.м
Цена за кв.м: 850 руб.
Общая стоимость: 17765 руб.
Нужен ремонт: true
Разберём, что здесь использовано:
lengthиwidth— переменныеfloat64(дробные числа, потому что размеры комнаты редко бывают целыми)area— вычисленная переменная (результат умножения)pricePerSquareMeter— константа (цена не меняется по ходу программы)totalCost— ещё одна вычисленная переменнаяroomName— переменнаяstring(текст)needsRepair— переменнаяbool(логическое значение)
Теперь усложним программу. Добавим вторую комнату и посчитаем общую площадь:
package main
import "fmt"
func main() {
// Комната 1
room1Name := "Гостиная"
room1Length := 5.5
room1Width := 3.8
room1Area := room1Length * room1Width
// Комната 2
room2Name := "Спальня"
room2Length := 4.2
room2Width := 3.0
room2Area := room2Length * room2Width
// Общая площадь
totalArea := room1Area + room2Area
// Стоимость
const pricePerSqM = 850.0
totalCost := totalArea * pricePerSqM
// Вывод
fmt.Println("=== Калькулятор площади квартиры ===")
fmt.Println()
fmt.Println(room1Name+":", room1Area, "кв.м")
fmt.Println(room2Name+":", room2Area, "кв.м")
fmt.Println()
fmt.Println("Общая площадь:", totalArea, "кв.м")
fmt.Println("Стоимость покрытия:", totalCost, "руб.")
// Проверяем, укладываемся ли в бюджет
var budget float64 = 30000.0
withinBudget := totalCost <= budget
fmt.Println("Бюджет:", budget, "руб.")
fmt.Println("Укладываемся:", withinBudget)
}
Результат:
=== Калькулятор площади квартиры ===
Гостиная: 20.9 кв.м
Спальня: 12.6 кв.м
Общая площадь: 33.5 кв.м
Стоимость покрытия: 28475 руб.
Бюджет: 30000 руб.
Укладываемся: true
Обратите внимание на строку withinBudget := totalCost <= budget. Оператор <= сравнивает два числа и возвращает bool: true, если стоимость меньше или равна бюджету. Здесь мы использовали все четыре базовых типа: float64 для размеров и цен, string для названий комнат, bool для результата сравнения, а константа заменила «магическое число».
✏️ Задание для самостоятельной работы
Попробуйте написать свою программу на основе того, что мы изучили. Вот идея:
Калькулятор стоимости поездки. Создайте переменные:
distance— расстояние в километрах (float64)fuelConsumption— расход топлива на 100 км (float64)fuelPrice— цена за литр бензина (const float64)passengers— количество пассажиров (int)destination— название города (string)
Посчитайте: сколько литров бензина нужно, общую стоимость, стоимость на одного пассажира. Выведите всё на экран.
Не бойтесь экспериментировать! Измените значения переменных, добавьте новые, попробуйте использовать разные типы. Чем больше практики — тем быстрее всё станет привычным.
📋 Итоги урока
- Переменная — именованное место в памяти для хранения данных
var name type = value— полное объявление,name := value— короткое (только внутри функций)const— неизменяемые значения, которые нельзя перезаписать- Четыре базовых типа:
int(целые числа),float64(дробные),string(текст),bool(true/false) - Нулевые значения (zero values):
int→ 0,float64→ 0.0,string→ "",bool→ false - Go требует явного приведения типов:
float64(myInt),int(myFloat) - Неиспользуемые переменные — ошибка компиляции. Go не позволяет мусорить
- Используйте понятные имена в стиле camelCase:
userName,totalPrice,isActive
В следующем уроке мы научимся общаться с пользователем: считывать данные с клавиатуры и красиво их выводить. Разберём пакет fmt во всех деталях — форматированный вывод, чтение ввода и превращение нашего калькулятора из «жёстко запрограммированного» в интерактивный, где пользователь сам вводит размеры комнаты.