Переменные в Go и работа с ними

    Команда Simple-Server
    03.06.2026
    20 мин

    Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.

    Кратко о задаче

    Все примеры кода, показанные в этом руководстве, запускаются в отдельных файлах с расширением .go.

    Далее наполняется содержимым в виде кода внутри функции main() с подключением всех необходимых модулей:

    package main import "fmt" func main() { // начало примера var number int = 10 fmt.Println(number) // конец примера }

    Существует градация вариантов того, как объявить переменную в Go, прежде чем ее использовать — от полной формы с явным указанием параметров переменной (или нескольких переменных) до краткой формы с автоопределением объявления и автовыводом типа.

    Использование каждой из форм объявления переменной зависит от контекста. Тем не менее, наиболее краткую и наиболее автоматическую запись рекомендуется использовать как можно чаще — она позволяет переложить часть ответственности на интерпретатор языка, тем самым снизив количество возможных ошибок по вине программиста.

    Наиболее явная форма объявления переменной в языке программирования Go предполагает указание ключевого слова var, имени переменной, ее типа и значения:

    var some_variable int = 5

    Однако при указании значения переменной явное указание типа можно опустить:

    При этом переменную можно объявить без присваивания значения, но в этом случае требуется указать тип:

    • var — ключевое слово объявления переменной
    • some_variable — произвольное имя переменной
    • int — тип переменной
    • 5 — значение переменной

    Например, вот так можно объявлять переменные строкового типа:

    var some_name string = "Ivan"

    А вот такое объявление переменной вызовет ошибку:

    // ОШИБКА: при объявлении не указано ни значение переменной, ни ее тип var some_name some_name = "Ivan"

    Важно помнить, что автовывод типа возможен только в момент объявления переменной, когда интерпретатор выделяет соответствующий объем оперативной памяти под ее значения.

    Несмотря на строгую статическую типизацию, Golang позволяет объявлять переменные в более лаконичной форме без явного указания ее параметров:

    В этом случае интерпретатор понимает, что необходимо автоматически вывести тип переменной исходя из указанного значения.

    Тем не менее, подобное объявление возможно только внутри функции (в том числе main()) — вне функции его использовать нельзя:

    package main // ОШИБКА: короткая форма объявления вне функции some_variable := 5 func main() { // ОК: короткая форма объявления внутри функции other_variable := 10 }

    При этом важно понимать отличие объявление переменной (вместе с инициализацией) от присвоения значения:

    package main func main() { some_variable := 5 // это объявление и инициализация (есть двоеточие) some_variable = 50 // это присвоение (нет двоеточия) other_variable = 7 // ОШИБКА: это присвоение (нет двоеточия) необъявленной переменной }

    Например, можно последовательно объявить (и инициализировать) несколько переменных:

    age := 50 // переменная типа int name := "Ivan" // переменная типа string occupation := "Just a guy" // переменная типа string height := 190.5 // переменная типа float32

    При этом оператор := нельзя использовать вместе с ключевым словом var. Если это сделать, возникнет ошибка:

    var someVariable int := 5 // ОШИБКА var someVariable := 5 // ОШИБКА

    Исключение ключевого слова var, но с явным указанием типа по прежнему вызывает ошибку:

    someVariable int := 5 // ОШИБКА

    В языке программирования Go можно объявить сразу несколько переменных в одной строке или блоке.

    Например, можно использовать ключевое слово var с указанием единого типа для всех объявляемых переменных:

    var width, height, depth int = 100, 200, 300

    Можно также разделить объявление переменных и присваивание значений:

    var width, height, depth int width, height, depth = 100, 200, 300

    Если типы переменных разные, то интерпретатор может вывести их типы автоматически:

    var name, age, fired = "Ivan", 50, false

    Аналогично можно использовать краткую форму для нескольких переменных:

    name, age, fired := "Ivan", 50, false

    В этом случае нет ни ключевого слова var, не указанных типов переменных.

    Еще один способ множественного объявления переменных — использование блока:

    var ( name string = "Ivan" age int = 50 height float64 = 190 fired bool = false )

    Кстати, блочное объявление можно отформатировать с помощью пробелов таким образом, чтобы имена, типы и значения выстраивались в несколько колонок, тем самым улучшая читаемость кода:

    var ( name string = "Ivan" age int = 50 height float64 = 190.5 fired bool = false )

    У блочного объявления переменных нет какого-либо утилитарного смысла. Это просто синтаксический сахар, который:

    • Улучшает читабельность кода, собирая важные переменные в одном месте.
    • Улучшает чистоту кода, исключая многократное использования ключевого слова var для каждой переменной.
    • Улучшает поддерживаемость кода, упрощая поиск и внесение изменений в параметры переменных.

    Таким образом, объявление в блоке оправдано только в тех случаях, когда необходимо сгруппировать несколько ключевых переменных, упростив их визуальное восприятие в текстовом редакторе кода.

    Создание переменной Go возможно без ее инициализации. В этом случае переменной будет присвоено нулевое значение, соответствующее указанному типу:

    • Для int, float32, float64 — 0, 0.0, 0.0
    • Для bool — false
    • Для string — ""
    • Для указателя — nil

    Эту особенность того, как Go обрабатывает объявление и инициализацию переменных, можно рассмотреть на примере реального скрипта:

    package main import "fmt" func main() { // целое число var numberInt int fmt.Println("Целое число:", numberInt) // вещественное число var numberFloat float32 fmt.Println("Вещественное число:", numberFloat) // строка var text string fmt.Println("Строка:", text) // булев var condition bool fmt.Println("Булев:", condition) // массив var array [5]int fmt.Println("Массив:", array) // срез var cut []int fmt.Println("Срез:", cut) // структура type S struct { name string size int address string } var structure S fmt.Println("Структура:", structure) // карта var dictionary map[int]int fmt.Println("Карта:", dictionary) // указатель var pointer *int fmt.Println("Указатель:", pointer) }

    Консольный вывод будет таким:

    Целое число: 0 Вещественное число: 0 Строка: Булев: false Массив: [0 0 0 0 0] Срез: [] Структура: { 0 } Карта: map[] Указатель: <nil>

    Как видно, переменные разных типов автоматически инициализируются нулевыми (или пустыми) значениями там, где это возможно.

    В языке программирования Go имена переменных могут начинаться либо с латинской буквы, либо с символа нижнего подчеркивания (_):

    onething := 123 // ОК Onething := 123 // ОК _onething := 123 // ОК __onething := 123 // ОК 1thing := 123 // ОШИБКА

    При этом у имени переменной есть одна функциональная особенность: имена, начинающиеся с заглавной буквы, видны в других пакетах, а начинающиеся с маленькой буквы — нет.

    Существует также несколько способов именования переменных, которые можно считать общими для всех языков программирования, в том числе и для Go:

    • Snake Case
    • Camel Case
    • Pascal Case
    • Kebab Case (не поддерживается в Go)

    При использовании Snake Case имя переменной выглядит так:

    some_random_variable := 123 // нижний регистр SOME_RANDOM_VARIABLE := 123 // верхний регистр

    При использовании Camel Case имя переменной выглядит так:

    someRandomVariable := 123

    При использовании Pascal Case имя переменной выглядит так:

    SomeRandomVariable := 123

    При использовании Kebab Case имя переменной выглядит так:

    // ОШИБКА some-random-variable := 123 // нижний регистр SOME-RANDOM-VARIABLE := 123 // верхний регистр

    Однако последний стиль именования переменных (Kebab Case) не поддерживается в языке Go из-за символа тире, который зарезервирован под операцию вычитания.

    ПРИМЕР: Объявление множества переменных

    Все показанные выше способы объявления переменных в языке программирования Go можно рассмотреть конкретнее на примере еще одного скрипта:

    package main import "fmt" func main() { // явное объявление с указанием типа var age int = 50 fmt.Println("Возраст:", age) // явное объявление с автоматическим выводом типа var height = 190.5 fmt.Println("Рост:", height) // краткое объявление name := "Ivan" fmt.Println("Имя:", name) // явное объявление нескольких переменных var width, depth int = 100, 200 fmt.Println("Ширина:", width, "Глубина:", depth) // явное объявление без инициализации var distance int fmt.Println("Дистанция:", distance) // блочное объявление нескольких переменных var ( occupation string = "Сварщик" category float32 = 3.4 license bool ) fmt.Println("Профессия:", occupation, "Разряд:", category, "Лицензия:", license) }

    Результатом работы этого кода станет следующий вывод в консольном терминале:

    Возраст: 50 Рост: 190.5 Имя: Ivan Ширина: 100 Глубина: 200 Дистанция: 0 Профессия: Сварщик Разряд: 3.4 Лицензия: false
    • Использование ключевого слова var необходимо для явного объявления переменной, особенно в глобальной области видимости.
    • Использование оператора := необходимо для краткого объявления переменной, особенно внутри функций.
    • Использование блока () необходимо для читабельного объявления целого множества переменных.

    При этом надо помнить, что в языке программирования Go предпочтительнее минимализм и лаконичность форм записи. Поэтому наиболее краткая форма записи должна использоваться везде, где это возможно.

    Все это позволяет снизить количество ошибок и сбоев, а также помогает поддерживать чистоту и читаемость кода.

    Как правило во время объявления переменной она вручную инициализируется каким-либо значением. При этом инициализация разных типов имеет синтаксические различия.

    Числовые переменные инициализируются присваиванием числового значения, что синтаксически выглядит тривиально:

    // int var someNumber int = 5 // float32 otherNumber := 10.0

    Число можно инициализировать другим числом:

    // int var someNumber int = 5 var otherNumber int = someNumber // int oneMoreNumber := someNumber

    Строковые переменные инициализируются присваиванием последовательности символов, заключенных в двойные кавычки:

    // string var someString string = "Здесь был какой-то программист"

    Строку можно также инициализировать другой строкой:

    // string var someString string = "Здесь был какой-то программист" var otherString string = someString // string oneMoreString := someString

    Инициализация булевых переменных ничем не отличается от инициализации числовых и строковых переменных за исключением того, что в качестве значения используется ключевое слово:

    // bool var someBool bool = true

    Аналогично, булевые переменные можно инициализировать другими булевыми переменными

    // bool var someBool bool = true var otherBool bool = someBool // bool oneMoreBool := someBool

    Есть несколько способов инициализации массива. Самый простой — с помощью поочередного доступа к элементам:

    // массив var languages [3]string planets[0] = "Golang" planets[1] = "Python" planets[2] = "Rust"

    Более сложный — через так называемый композитный литерал.

    Композитный литерал — компактная синтаксическая конструкция для инициализации любого композитного (составного) типа, исключающая последовательное присваивание каждого элемента.

    Таким образом массив можно инициализировать целиком за один шаг:

    var languages = [3]string{"Golang", "Python", "Rust"}

    Или использовать краткую форму:

    languages := [3]string{"Golang", "Python", "Rust"}

    Также инициализировать элементы массива можно частично:

    // размер массива 5, а инициализировано элементов 3 languages := [5]string{"Golang", "Python", "Rust"} languages[3] = "Java" languages[4] = "C++"

    А с помощью такой записи инициализацию большого массива можно сделать более читабельной:

    languages := [5]string{ "Golang", "Python", "Rust", "Java", "C++", // запятая в конце ОБЯЗАТЕЛЬНА }

    Кстати, массив можно инициализировать другим массивом, скопировав все его элементы:

    languages := [3]string{"Golang", "Python", "Rust"} otherLanguages := languages

    При этом важно понимать, что копирование массива также выполняется при его передаче в функцию:

    package main import "fmt" func change(languages [5]string) { for i := range languages { languages[i] = "[" + languages[i] + "]" } } func main() { languages := [5]string{ "Golang", "Python", "Rust", "Java", "C++", } change(languages) fmt.Println(languages) }

    Вывод в консольный терминал будет следующим:

    [Golang Python Rust Java C++]

    Таким образом изменениям подверглась только копия массива внутри функции change(), а не оригинальный массив из функции main().

    Тем не менее, явная инициализация массива другим массивом возможна только в том случае, если оба массива имеют одинаковую длину и тип:

    languages := [3]string{"Golang", "Python", "Rust"} var otherLanguages [3]string = languages // ОК var oneMoreLanguages [4]string = languages // ОШИБКА

    Помимо этого, в языке Go можно создавать массивы из произвольного числа других массивов. При этом, инициализировать элементы таких массивов можно как последовательно:

    var matrix [2][2]string matrix[0][0] = "a" matrix[0][1] = "b" matrix[1][0] = "c" matrix[1][1] = "d"

    Так и с помощью композитного литерала:

    var matrix = [2][2][2]string{{{"a", "b"}, {"c", "d"}}, {{"e", "f"}, {"g", "h"}}}

    Как видно, второй вариант занимает меньше места, но синтаксически более сложен.

    Срез инициализируется также, как и массив:

    var languages = []string{"Golang", "Python", "Rust"}

    Однако в отличие от массива, срез можно инициализировать другим срезом произвольной длины:

    var languages = []string{"Golang", "Python", "Rust"} var otherLanguages []string = languages

    Карты инициализируются через композитный литерал с указанием типа ключа и значения. Содержимое же перечисляется через запятую, разделяясь двоеточием:

    var languages = map[string]string{"first": "Golang", "second": "Python", "third": "Rust"}

    Можно также использовать короткую форму объявления и более читабельный вид инициализации:

    languages := map[string]string{ "first": "Golang", "second": "Python", "third": "Rust", // запятая в конце ОБЯЗАТЕЛЬНА }

    При этом инициализация карты другой картой не копирует элементы, а делает их общими:

    package main import "fmt" func main() { languages := map[string]string{"first": "Golang", "second": "Python", "third": "Rust"} otherLanguages := languages fmt.Println(languages) fmt.Println(otherLanguages) otherLanguages["first"] = "C++" fmt.Println(languages) fmt.Println(otherLanguages) delete(otherLanguages, "second") fmt.Println(languages) fmt.Println(otherLanguages) }

    Консольный вывод этого примера будет таким:

    map[first:Golang second:Python third:Rust] map[first:Golang second:Python third:Rust] map[first:C++ second:Python third:Rust] map[first:C++ second:Python third:Rust] map[first:C++ third:Rust] map[first:C++ third:Rust]

    Как можно заметить, любое изменение в одной из карт влияет также на другую.

    Указатели можно инициализировать только адресом переменной такого же типа:

    var variable int = 15 var pointer *int = &variable

    Символ амперсанда (&) позволяет получить адрес любой переменной:

    package main import "fmt" func main() { var variable int = 15 var pointer *int = &variable fmt.Println(pointer) }

    Консольный вывод этого примера будет примерно таким:

    Для инициализации указателей можно также использовать краткую запись:

    variable := 15 pointer := &variable

    Для того, чтобы получить значение по адресу указателя, его нужно разыменовать с помощью символа звездочки (*):

    package main import "fmt" func main() { var variable int = 15 var pointer *int = &variable fmt.Println(*pointer) }

    В этом случае в терминале консоли появится такой вывод:

    Таким образом можно присваивать новые значения переменной, расположенной по адресу указателя:

    package main import "fmt" func main() { var variable int = 15 var pointer *int = &variable *pointer = 5 fmt.Println(*pointer) }

    В консоли появится такой вывод:

    Наконец, указатель можно инициализировать безымянным объектом в памяти. Для этого используется функция new(), которая возвращает адрес выделенной области памяти:

    variable := new(int) *variable = 15

    Удалять же выделенную область памяти вручную не надо — этим автоматически занимается сборщик мусора.

    Структуру можно инициализировать либо последовательно указанными значениями:

    type something struct { first string second int } var structure something = something{"Ivan", 15}

    Либо значениями, указанными явно по ключам:

    type something struct { first string second int } var structure something = something{second: 15, first: "Ivan"}

    А можно вообще не указывать никаких значений, тем самым автоматически инициализировать все нулями:

    package main import "fmt" type something struct { first string second int } func main() { var structure something = something{} fmt.Println(structure) structure.first = "Ivan" structure.second = 15 fmt.Println(structure) }

    В этом случае консольный вывод будет таким:

    Ветвление на основе переменных

    Переменные занимают центральное место в ветвлениях. На основе их значений (по условию) выполняются различные участки кода программы.

    Самая базовая условная конструкция создается операторами if/else. Так выглядит наиболее простое условие:

    a := 5 b := 10 if a < b { fmt.Println("A меньше B") }

    Например, с помощью простого условия можно проверить указатель:

    var pointer *int if pointer == nil { fmt.Println("Нет адреса") }

    Более сложная форма описывается так:

    a := 10 b := 5 if a < b { fmt.Println("A меньше B") } else { fmt.Println("A больше B") }

    А с помощью комбинации else и if можно создавать еще более сложные конструкции:

    a := 10 b := 5 if a < b { fmt.Println("A меньше B") } else if a > b { fmt.Println("A больше B") } else { fmt.Println("A равно B") }

    При этом выражений if/else может быть несколько:

    a := 12 if a < 5 { fmt.Println("A меньше 5") } else if a < 10 { fmt.Println("A меньше 10") } else if a < 20{ fmt.Println("A меньше 20") } else { fmt.Println("A в суперпозиции") }

    Еще один способ ветвления — конструкция switch, внутри которой задаются возможные значения переменной и действия, которые нужно выполнить, если есть совпадение:

    a := 1 switch(a) { case 0: fmt.Println("A равно 0") case 1: fmt.Println("A равно 1") case 2: fmt.Println("A равно 2") }

    С помощью секции default можно задать действие, выполняющееся при отсутствии совпадений:

    a := 3 switch(a) { case 0: fmt.Println("A равно 0") case 1: fmt.Println("A равно 1") case 2: fmt.Println("A равно 2") default: fmt.Println("A в суперпозиции") }

    Можно также объединить несколько возможных совпадений внутри одной секции:

    a := 1 switch(a) { case 0, 1, 2: fmt.Println("A равно либо 0, либо 1, либо 2") default: fmt.Println("A в суперпозиции") }

    В языке Go есть множество дополнительных функций для работы с переменными. В этом руководстве разберём лишь основные из них.

    В языке Go есть специальные системные функции, позволяющие как установить переменную окружения, так и получить ее значение:

    package main import ( "fmt" "os" "strings" ) func main() { os.Setenv("SOMEVAR", "1") // записываем переменную окружения fmt.Println("SOMEVAR:", os.Getenv("SOMEVAR")) // читаем переменную окружения }

    Часто логика программы требует измерения времени. В языке Go для этого есть соответствующий инструмент — переменная типа time.

    Надо сказать, что время — это отдельная обширная тема. Узнать же больше о пакете time можно в официальной документации.

    В этом же руководстве будет показано, как узнать текущее время в различных форматах:

    package main import ( "fmt" "time" ) func main() { fmt.Println("Текущее время:", time.Now()) fmt.Println("Текущее время (UTC):", time.Now().UTC()) fmt.Println("Текущее время (Unix):", time.Now().Unix()) }

    В консольном терминале появится следующий вывод:

    Текущее время: 2009-11-10 23:00:00 +0000 UTC m=+0.000000001 Текущее время (UTC): 2009-11-10 23:00:00 +0000 UTC Текущее время (Unix): 1257894000

    Можно также уточнить конкретный параметр времени:

    package main import ( "fmt" "time" ) func main() { timeNow := time.Now() fmt.Println("Общее время:", timeNow) fmt.Println("Год:", timeNow.Year()) fmt.Println("Месяц:", timeNow.Month()) fmt.Println("День:", timeNow.Day()) fmt.Println("Часы:", timeNow.Hour()) fmt.Println("Минуты:", timeNow.Hour()) fmt.Println("Секунды", timeNow.Second()) }

    В этом случае консольный вывод будет таким:

    Общее время: 2024-11-15 23:46:09.157929822 +0000 UTC m=+0.000031801 Год: 2024 Месяц: November День: 15 Часы: 23 Минуты: 23 Секунды 9

    Добавление и удаление элементов среза

    К срезам можно добавлять элементы:

    var languages = []string{"Golang", "Python", "Rust"} languages = append(languages, "Java", "C++") fmt.Println(languages)

    Или удалять элементы из них:

    var languages = []string{"Golang", "Python", "Rust"} // удаление 2-го элемента n := 1 languages = append(languages[:n], languages[n+1:]...) fmt.Println(languages)

    Удаление в данном случае выполняется с помощью оператора среза, который создает из одной последовательности другую.

    package main import "fmt" func main() { var sequence = []string{"One", "Two", "Three", "Four", "Five"} newSequence := sequence[1:4] // элементы в диапазоне от 1 до 3 станут содержимым нового среза fmt.Println(newSequence) }

    В консольном терминале будет следующий вывод:

    Тип переменной можно узнать с помощью функции TypeOf(), которая содержится в модуле reflect:

    package main import ( "fmt" "reflect" // модуль, позволяющий узнать тип ) func main() { variableString := "строка" variableInt := 5 variableFloat64 := 1.5 variableBool := true fmt.Println(reflect.TypeOf(variableString)) fmt.Println(reflect.TypeOf(variableInt)) fmt.Println(reflect.TypeOf(variableFloat64)) fmt.Println(reflect.TypeOf(variableBool)) }

    Консольный вывод этого примера будет следующим:

    Часто необходимо вставить переменную в строку. Сделать это можно несколькими способами:

    package main import "fmt" func main() { // СПОСОБ 1 stringPre := "человекочитаемая" stringEnd1 := fmt.Sprintf("Это %s строка", stringPre) fmt.Println(stringEnd1) // СПОСОБ 2 stringEnd2 := "Это " + stringPre + " строка" fmt.Println(stringEnd2) }

    В консоли появится следующий вывод:

    Это человекочитаемая строка Это человекочитаемая строка

    Также можно комбинировать числовые переменные со строковыми:

    package main import "fmt" func main() { name := "Иван" age := 50 fmt.Printf("Привет, меня зовут %v и мне %v лет.\n", name, age) }

    В этом случае вывод будет таким:

    Привет, меня зовут Иван и мне 50 лет.

    Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.

    VPS для проекта

    VPS с root-доступом, NVMe и поддержкой 24/7 на Simple-Server.

    StarterVDS

    490₽

    в месяц

    1 ядро

    1 ГБ RAM

    20 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Безлимитный трафик
    Заказать VPS
    Рекомендуем

    PerformanceVDS

    1190₽

    в месяц

    2 ядра

    4 ГБ RAM

    60 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Базовая DDoS-защита
    Заказать VPS

    Нужна другая конфигурация или чистый VPS без панели?

    Все тарифы VPS

    Похожие статьи, которые могут быть вам интересны