🐹 Go
गो में चर
Переменные и типы в Go: var, := и все типы данных
Переменные — это именованные ячейки памяти для хранения данных. В Go есть интересная особенность: два способа объявить переменную — через var и через оператор :=. И у каждого типа есть своё значение «по умолчанию» — zero value. Давай разберёмся!
Два способа объявить переменную
package main
import "fmt"
func main() {
// Способ 1: var (явное объявление)
var age int = 16
var name string = "Алиса"
var isStudent bool = true
fmt.Println(age, name, isStudent)
// Способ 2: := (краткое объявление, только внутри функций)
score := 95 // int
city := "Москва" // string
height := 1.75 // float64
fmt.Println(score, city, height)
// var без значения (будет zero value)
var count int // = 0
var title string // = ""
var active bool // = false
fmt.Println(count, title, active) // 0 false
}
Zero values: значения по умолчанию
В Go каждый тип имеет нулевое значение (zero value). Это как пустые коробки на складе: коробки есть, но они пустые. Ты знаешь, что там: числа — 0, строки — пусто, булевы — ложь.
package main
import "fmt"
func main() {
var i int // 0
var f float64 // 0.0
var s string // "" (пустая строка)
var b bool // false
var p *int // nil (нулевой указатель)
fmt.Printf("int: %d\n", i)
fmt.Printf("float64: %f\n", f)
fmt.Printf("string: %q\n", s) // %q добавляет кавычки
fmt.Printf("bool: %t\n", b)
fmt.Printf("pointer: %v\n", p)
// int: 0
// float64: 0.000000
// string: ""
// bool: false
// pointer:
}
Числовые типы
package main
import "fmt"
func main() {
// Целые числа
var a int8 = 127 // -128 до 127
var b int16 = 32767 // ~±32 тыс
var c int32 = 2147483647 // ~±2 млрд
var d int64 = 9223372036854775807 // ~±9×10^18
// int — зависит от платформы (32 или 64 бита, обычно 64)
var e int = 42
// Беззнаковые
var f uint = 100 // только положительные
// Числа с плавающей точкой
var g float32 = 3.14 // 7 значимых цифр
var h float64 = 3.14159265358979 // 15-17 значимых цифр
// Комплексные числа (редко нужны)
var k complex128 = 3 + 4i
fmt.Println(a, b, c, d, e, f)
fmt.Println(g, h)
fmt.Println(k) // (3+4i)
// Математика
x := 17
y := 5
fmt.Println(x + y) // 22
fmt.Println(x - y) // 12
fmt.Println(x * y) // 85
fmt.Println(x / y) // 3 (целочисленное деление!)
fmt.Println(x % y) // 2 (остаток)
}
Строки и символы
package main
import (
"fmt"
"strings"
)
func main() {
// Строки в двойных кавычках
name := "Привет, мир!"
// Длина строки (в байтах!)
fmt.Println(len(name)) // 23 для UTF-8 (русские буквы — 2 байта)
// Конкатенация
firstName := "Иван"
lastName := "Петров"
fullName := firstName + " " + lastName
fmt.Println(fullName) // Иван Петров
// Методы строк
fmt.Println(strings.ToUpper(name)) // ПРИВЕТ, МИР!
fmt.Println(strings.ToLower(name)) // привет, мир!
fmt.Println(strings.Contains(name, "мир")) // true
fmt.Println(strings.Replace(name, "мир", "Go", 1)) // Привет, Go!
fmt.Println(strings.Split("a,b,c", ",")) // [a b c]
// Многострочная строка (backtick)
multiline := `Строка 1
Строка 2
Строка 3`
fmt.Println(multiline)
// Rune — для работы с Unicode символами
text := "Привет"
runes := []rune(text)
fmt.Println(len(runes)) // 6 (6 символов, а не байтов)
}
Тип bool и операции
package main
import "fmt"
func main() {
isRaining := false
isCold := true
// Логические операции
fmt.Println(isRaining && isCold) // false (И)
fmt.Println(isRaining || isCold) // true (ИЛИ)
fmt.Println(!isRaining) // true (НЕ)
// Сравнения возвращают bool
a, b := 10, 5
fmt.Println(a == b) // false
fmt.Println(a != b) // true
fmt.Println(a > b) // true
fmt.Println(a < b) // false
fmt.Println(a >= b) // true
fmt.Println(a <= b) // false
}
Множественное присваивание
package main
import "fmt"
func main() {
// Несколько переменных в одной строке
x, y := 10, 20
fmt.Println(x, y) // 10 20
// Обмен переменных — элегантно!
x, y = y, x
fmt.Println(x, y) // 20 10
// Объявление нескольких var
var (
name string = "Алиса"
age int = 20
isAdult bool = true
)
fmt.Println(name, age, isAdult)
// Discard — игнорировать значение
a, _ := 10, 20 // _ означает "мне не нужно это значение"
fmt.Println(a) // 10
}
Константы
package main
import "fmt"
// Константы объявляются с const
const Pi = 3.14159265358979
const MaxPlayers = 100
const AppName = "МояИгра"
// Группа констант
const (
StatusOK = 200
StatusError = 500
AppVersion = "1.0.0"
)
func main() {
// Нельзя изменить константу
// Pi = 3.14 // ОШИБКА: cannot assign to Pi
fmt.Printf("Площадь круга r=5: %.2f\n", Pi * 5 * 5)
fmt.Printf("Максимум игроков: %d\n", MaxPlayers)
}
iota: автоматические счётчики для enum
package main
import "fmt"
// iota — автоинкремент для констант (аналог enum)
type Direction int
const (
North Direction = iota // 0
East // 1
South // 2
West // 3
)
type Day int
const (
Monday Day = iota + 1 // 1 (iota=0, +1=1)
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
Sunday // 7
)
// Степени двойки с iota
const (
KB = 1 << (10 * (iota + 1)) // 1024
MB // 1048576
GB // 1073741824
)
func main() {
dir := North
fmt.Println(dir) // 0
fmt.Println(Monday, Tuesday, Wednesday) // 1 2 3
fmt.Printf("KB=%d, MB=%d, GB=%d\n", KB, MB, GB)
// KB=1024, MB=1048576, GB=1073741824
// Использование в switch
day := Wednesday
switch day {
case Monday, Tuesday, Wednesday, Thursday, Friday:
fmt.Println("Рабочий день")
case Saturday, Sunday:
fmt.Println("Выходной!")
}
}
Преобразование типов
package main
import (
"fmt"
"strconv"
)
func main() {
// В Go нет неявного преобразования! Только явное
var i int = 42
var f float64 = float64(i) // явное преобразование
var u uint = uint(f)
fmt.Println(i, f, u) // 42 42 42
// ОШИБКА без преобразования:
// var x float64 = 42 + i // mismatched types
// Строка ↔ число
numStr := "123"
num, err := strconv.Atoi(numStr) // string → int
if err != nil {
fmt.Println("Ошибка:", err)
} else {
fmt.Println(num + 1) // 124
}
str := strconv.Itoa(456) // int → string
fmt.Println(str + "!") // 456!
// float string
f2, _ := strconv.ParseFloat("3.14", 64)
fmt.Println(f2) // 3.14
}
Итого
- ✅ var — явное объявление переменной (можно использовать везде)
- ✅ := — краткое объявление (только внутри функций, определяет тип автоматически)
- ✅ Zero values — все переменные инициализируются по умолчанию: 0, "", false, nil
- ✅ int, float64, string, bool — основные типы данных
- ✅ const — константа, нельзя изменить
- ✅ iota — автоматический счётчик для группы констант (аналог enum)
- ✅ В Go нет неявного преобразования типов — всегда нужно явно: float64(x)
Тип rune: работа с Unicode
package main
import "fmt"
func main() {
// string — это байты, а не символы!
s := "Привет"
fmt.Println(len(s)) // 12 (байт, не символов — кириллица 2 байта)
// rune — это int32, представляет Unicode code point
runes := []rune(s)
fmt.Println(len(runes)) // 6 (символов)
// Правильный перебор символов
for i, r := range s {
fmt.Printf("index=%d char=%c code=%d\n", i, r, r)
}
// Срезы строки по символам (не байтам)
r := []rune(s)
fmt.Println(string(r[0:3])) // "При"
}
Тип byte: работа с бинарными данными
package main
import "fmt"
func main() {
// byte = uint8 = число от 0 до 255
var b byte = 255
// Строка — это []byte в Go
s := "Hello"
bytes := []byte(s)
fmt.Println(bytes) // [72 101 108 108 111]
// Изменение строки через байты
bytes[0] = 'h'
fmt.Println(string(bytes)) // "hello"
// Полезно при работе с сетью, файлами, криптографией
}
Указатели в Go
package main
import "fmt"
func main() {
x := 42
// & — адрес переменной (получить указатель)
p := &x
fmt.Println(p) // 0xc0000b4008 (адрес в памяти)
fmt.Println(*p) // 42 (разыменование — значение по адресу)
// Изменение через указатель
*p = 100
fmt.Println(x) // 100 — x изменился!
// new — выделить память и вернуть указатель
n := new(int) // *int, значение 0
*n = 55
fmt.Println(*n) // 55
// Указатели на struct (часто используется)
type Point struct{ X, Y int }
pt := &Point{X: 3, Y: 4}
pt.X = 10 // Go автоматически разыменовывает: (*pt).X = 10
fmt.Println(pt) // &{10 4}
}
Массивы и срезы
package main
import "fmt"
func main() {
// Массив — фиксированный размер
var arr [5]int = [5]int{1, 2, 3, 4, 5}
arr2 := [3]string{"Go", "Python", "Rust"}
arr3 := [...]int{10, 20, 30} // ... = компилятор считает размер
fmt.Println(arr[0]) // 1
fmt.Println(len(arr)) // 5
// Срез (slice) — динамический массив, ОСНОВНАЯ коллекция в Go
s := []int{1, 2, 3, 4, 5}
s2 := make([]int, 5) // [0 0 0 0 0]
s3 := make([]int, 3, 10) // длина 3, ёмкость 10
fmt.Println(len(s), cap(s)) // 5, 5
// Добавление элементов
s = append(s, 6, 7, 8)
fmt.Println(s) // [1 2 3 4 5 6 7 8]
// Срезы среза
fmt.Println(s[1:4]) // [2 3 4]
fmt.Println(s[:3]) // [1 2 3]
fmt.Println(s[3:]) // [4 5 6 7 8]
// Копирование
dst := make([]int, len(s))
copy(dst, s)
_ = s2; _ = s3; _ = arr2; _ = arr3; _ = dst
}
Map: словарь ключ-значение
package main
import "fmt"
func main() {
// Создание map
ages := map[string]int{
"Алиса": 20,
"Борис": 25,
"Вера": 22,
}
// Доступ к значению
fmt.Println(ages["Алиса"]) // 20
// Проверка существования ключа
age, ok := ages["Гриша"]
if ok {
fmt.Println("Возраст:", age)
} else {
fmt.Println("Гриша не найден")
}
// Добавление и изменение
ages["Гриша"] = 19
ages["Алиса"] = 21 // Обновляем
// Удаление
delete(ages, "Борис")
// Перебор (порядок не гарантирован!)
for name, age := range ages {
fmt.Printf("%s: %d лет\n", name, age)
}
fmt.Println("Всего:", len(ages))
// make для создания map
scores := make(map[string][]int)
scores["Алиса"] = []int{85, 92, 78}
scores["Борис"] = append(scores["Борис"], 75)
fmt.Println(scores)
}
Итого
- ✅ var — явное объявление переменной
- ✅ := — краткое объявление (только внутри функций)
- ✅ Zero values: int=0, float=0.0, string="", bool=false, pointer=nil
- ✅ int, float64, string, bool — основные типы
- ✅ rune (int32) — символ Unicode; byte (uint8) — байт
- ✅ const — неизменяемое значение
- ✅ iota — автоинкремент для группы констант (аналог enum)
- ✅ В Go нет неявных преобразований — только явные:
float64(x) - ✅ []T (срез) — основная коллекция в Go
- ✅ map[K]V — словарь ключ-значение
Работа с числами: стандартные операции
package main
import (
"fmt"
"math"
)
func main() {
// Математические операции
a, b := 17, 5
fmt.Println(a + b) // 22
fmt.Println(a - b) // 12
fmt.Println(a * b) // 85
fmt.Println(a / b) // 3 (целочисленное!)
fmt.Println(a % b) // 2 (остаток)
// Операторы присваивания
x := 10
x += 5 // 15
x -= 3 // 12
x *= 2 // 24
x /= 4 // 6
x %= 4 // 2
fmt.Println(x)
// Инкремент/декремент (только постфиксный в Go!)
i := 5
i++ // i = 6
i-- // i = 5
// В Go нет ++i или --i (только i++ и i--)
// Математические функции
fmt.Printf("sqrt(16) = %.0f\n", math.Sqrt(16)) // 4
fmt.Printf("pow(2,8) = %.0f\n", math.Pow(2, 8)) // 256
fmt.Printf("abs(-42) = %.0f\n", math.Abs(-42)) // 42
fmt.Printf("floor(3.7) = %.0f\n", math.Floor(3.7)) // 3
fmt.Printf("ceil(3.2) = %.0f\n", math.Ceil(3.2)) // 4
fmt.Printf("round(3.5) = %.0f\n", math.Round(3.5)) // 4
}
Практика: конвертер температур
package main
import "fmt"
func celsiusToFahrenheit(c float64) float64 { return c*9/5 + 32 }
func fahrenheitToCelsius(f float64) float64 { return (f - 32) * 5 / 9 }
func celsiusToKelvin(c float64) float64 { return c + 273.15 }
func main() {
temperatures := []float64{-40, 0, 20, 37, 100}
fmt.Printf("%-8s %-12s %-12s\n", "Цельсий", "Фаренгейт", "Кельвин")
fmt.Println(fmt.Sprintf("%s", "─────────────────────────────────"))
for _, c := range temperatures {
fmt.Printf("%-8.1f %-12.1f %-12.2f\n",
c,
celsiusToFahrenheit(c),
celsiusToKelvin(c))
}
}
Форматирование и вывод разных типов
package main
import "fmt"
func main() {
// Типы и их zero values
var i int; var f float64; var s string; var b bool
fmt.Printf("int: %d, float64: %f, string: %q, bool: %t\n", i, f, s, b)
// int: 0, float64: 0.000000, string: "", bool: false
// Таблица форматирования числа
n := 255
fmt.Printf("Десятичное: %d\n", n) // 255
fmt.Printf("Двоичное: %b\n", n) // 11111111
fmt.Printf("Восьмеричное: %o\n", n) // 377
fmt.Printf("Шестнадц.: %x\n", n) // ff
fmt.Printf("Шестнадц.: %X\n", n) // FF
fmt.Printf("Символ: %c\n", 65) // A
// Выравнивание
fmt.Printf("|%10d|\n", n) // | 255| (право)
fmt.Printf("|%-10d|\n", n) // |255 | (лево)
fmt.Printf("|%010d|\n", n) // |0000000255| (нули)
fmt.Printf("|%+d|\n", n) // |+255| (знак)
// Числа с плавающей точкой
pi := 3.14159265358979
fmt.Printf("%.2f\n", pi) // 3.14
fmt.Printf("%.5f\n", pi) // 3.14159
fmt.Printf("%e\n", pi) // 3.141593e+00
fmt.Printf("%g\n", pi) // 3.14159265358979
}
Итого
- ✅ var и := — два способа объявить переменную
- ✅ Zero values — переменные инициализируются по умолчанию
- ✅ iota — автоинкремент для констант (аналог enum)
- ✅ Явные преобразования типов обязательны в Go
- ✅ []T — срез (динамический массив), map[K]V — словарь