---
title: "Первая программа"
description: "Go — это язык, на котором пишут серверы, утилиты командной строки и большие распределённые системы. В этой главе мы не будем городить ничего сложного: напишем самую первую…"
canonical: https://graphlms.ru/go-basics/book/hello
course: "Основы Go"
updated: 2026-10-12
lang: ru
publisher: GraphLMS
---

# Первая программа

> Источник: https://graphlms.ru/go-basics/book/hello — курс «Основы Go», GraphLMS.

## О чём глава

Go — это язык, на котором пишут серверы, утилиты командной строки и большие распределённые системы. В этой главе мы не будем городить ничего сложного: напишем самую первую программу, разберём, из каких обязательных частей она состоит, и научимся выводить текст и значения на экран. К концу главы вы поймёте, что происходит, когда вы запускаете программу командой `go run`, чем она отличается от `go build`, и как печатать не только «Hello, world», но и числа, строки и даже типы переменных.

Никакого предыдущего опыта с Go не нужно. Если вы вообще никогда не писали код — тоже ничего страшного, мы идём медленно.

## Как проходить курс

Для начала достаточно браузера. Примеры с кнопкой «запустить» можно менять и выполнять прямо на странице. Привычка, которая окупается быстрее всего: прежде чем нажать кнопку, предскажите вывод, а потом сравните. Ошиблись в предсказании — значит, нашли место, которое стоит перечитать.

Кнопка запускает код не настоящим Go, а интерпретатором прямо в браузере. Примеры курса мы сверяли с настоящим `go run`, но интерпретатор всё же не компилятор: нет пакета `testing`, сети и файлов, а параллельности горутин нет. Такие примеры даны без кнопки, с готовым выводом; проверить их можно на своём компьютере (как — ниже в этой главе).

В конце каждой главы есть упражнение и решение для проверки. Время в заголовке главы — это время чтения; на упражнения закладывайте отдельно.

## Что вообще такое Go

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

**Go компилируемый.** Это значит, что ваш текст программы (исходный код) сначала переводится в машинный код — готовый исполняемый файл, который процессор понимает напрямую. В отличие от языков вроде Python или JavaScript, где код читает и исполняет отдельная программа-интерпретатор «на лету», у Go есть отдельный шаг — компиляция. Платим мы за это секундами ожидания при сборке, а получаем быстрый запуск и единый файл, который можно просто скопировать на сервер и запустить.

**Go статически типизированный.** У каждого значения есть тип, известный заранее: число, строка, логическое значение и так далее. Компилятор проверяет типы ещё до запуска. Если вы попробуете сложить строку с числом по ошибке, программа просто не соберётся — и вы узнаете о проблеме сразу, а не когда она уже «выстрелит» у пользователя. Это очень удобно: компилятор работает вашим первым ревьюером.

**В Go есть сборщик мусора (garbage collector).** Память под данные выделяется автоматически, и когда данные больше не нужны, среда исполнения сама их освобождает. Вам не нужно вручную «возвращать» память, как в C. Это снимает целый класс ошибок и даёт сосредоточиться на логике.

Держите эти три свойства в голове — они будут объяснять поведение Go во всех следующих главах.

## Скелет программы: package main и func main

Любая исполняемая Go-программа начинается с одного и того же каркаса. Вот он целиком:

```go play
package main

import "fmt"

func main() {
	fmt.Println("Привет, Go!")
}
```

Разберём по строчкам, потому что здесь нет ни одной лишней.

`package main` — это объявление пакета. Пакет — это набор файлов, которые живут вместе и образуют одну логическую единицу. Имя `main` особенное: оно говорит компилятору, что из этого пакета нужно собрать запускаемую программу, а не библиотеку. Если пакет называется иначе — это библиотека, которую подключают к другим программам.

`import "fmt"` подключает стандартный пакет `fmt` (от слова *format*). Именно в нём лежат функции для вывода текста, которыми мы пользуемся ниже. Чтобы пользоваться чужим кодом, его нужно сначала импортировать.

`func main()` — это функция с именем `main`. Она тоже особенная: с неё начинается выполнение программы. Когда вы запускаете собранный файл, Go находит `main` в пакете `main` и вызывает её. Всё, что между фигурными скобками `{ }`, — тело функции, то есть инструкции, которые выполнятся по порядку сверху вниз.

Запомните пару: **пакет `main` + функция `main`**. Без этой пары запускать нечего: компилятор не будет знать, откуда стартовать.

Дальше в курсе вы встретите два вида примеров. Полный пример начинается с `package main` и содержит `func main()`: его можно запускать как есть. Фрагмент показывает только часть программы, и его нужно вставить в каркас. Правило вставки простое. Объявления (`func ...`, `type ...`) пишутся снаружи `main`, рядом с ней. Действия — вызовы функций, присваивания, циклы — внутри `main`:

```go play
package main

import "fmt"

// объявление функции — снаружи main
func double(x int) int {
	return x * 2
}

func main() {
	// действия — внутри main
	fmt.Println(double(21))
}
```

Эта программа напечатает `42`. Как устроены функции вроде `double`, подробно разберём в четвёртой главе; пока важно только, где что стоит.

## Запускаем: hello world

Попробуем вживую. Нажмите «запустить» под примером — программа выполнится прямо в браузере.

```go play
package main

import "fmt"

func main() {
	fmt.Println("Привет, Go!")
	fmt.Println("Это моя первая программа.")
}
```

`fmt.Println` печатает то, что вы ей передали, и переводит строку (суффикс `ln` — от *line*). Каждый вызов — с новой строки. Если передать несколько значений через запятую, они напечатаются в одну строку через пробел:

```go play
package main

import "fmt"

func main() {
	fmt.Println("сумма", 2, "и", 3, "равна", 2+3)
}
```

Вывод: `сумма 2 и 3 равна 5`. Мы смешали строки и числа в одном вызове, и Go спокойно их вывел; выражение `2+3` вычислилось до печати. `Println` умеет печатать значения любого типа.

## Первый запуск на своём компьютере

Для кнопки запуска установка не нужна. Локальный Go понадобится для многофайловых проектов, тестов, примеров с сетью и файлами и проверки гонок. Установите Go по [официальной инструкции](https://go.dev/doc/install). Терминал — окно, куда вводят команды; строку команды подтверждают клавишей Enter. Откройте терминал и выполните:

```bash
go version
```

Если появилась версия Go, установка доступна. Если команда не найдена, сначала завершите установку и откройте терминал заново. Создайте отдельную папку `go-study` через файловый менеджер и откройте её в редакторе кода. Терминал редактора должен находиться в этой папке. При необходимости перейдите в неё командой `cd`: например, `cd "/Users/anna/Documents/Go study/go-study"` в macOS или `cd "C:\Users\Anna\Documents\Go study\go-study"` в PowerShell. Замените пример своим путём. `cd` меняет рабочую папку, а кавычки сохраняют путь с пробелами.

Сохраните первый полный пример этой главы в файл `main.go`; проверьте, что расширение не стало `.go.txt`. В папке с этим файлом выполните:

```bash
go mod init example.com/go-study
go run .
```

Первая команда один раз создаёт `go.mod` — описание проекта. Домен `example.com` здесь часть учебного имени; создавать сайт или репозиторий не нужно. Подробнее модуль разобран в главе [«Пакеты и модули»](/go-basics/book/packages-modules). Вторая команда собирает и запускает пакет в текущей папке: точка означает «здесь». Проверка: появилась строка `Привет, Go!`.

Для следующей полной программы заменяйте содержимое `main.go`. Если оставить несколько функций `main` в одном пакете, сборка не начнётся. Сообщение компилятора обычно содержит имя файла и номер строки: найдите эту строку, исправьте ошибку и запустите снова. Если сообщение говорит об отсутствии `go.mod`, проверьте, в той ли папке находится терминал.

## go run и go build

На своём компьютере (не в браузере) вы запускаете Go двумя основными командами. Разница между ними простая, но важная.

`go run .` берёт исходный код, компилирует его во временный файл, тут же запускает и выкидывает результат. Удобно во время разработки: правишь код, набираешь `go run .`, сразу видишь итог. Готового файла после этого не остаётся.

```bash
go run .
```

`go build -o app` компилирует код в исполняемый файл с выбранным именем `app`. Его можно запускать без повторной компиляции. Для другой операционной системы или архитектуры процессора программу обычно собирают отдельно.

```bash
go build -o app
./app
```

В Windows используйте `go build -o app.exe`, затем `.\app.exe` в PowerShell. Без `-o` файл получит имя по последней части имени модуля: для `example.com/go-study` это `go-study`. Явное имя просто удобнее.

Если коротко: `go run` — «собери и запусти разок, прямо сейчас», `go build` — «собери готовую программу, я буду запускать её сам». В браузере кнопка делает всё за вас, но в настоящем проекте вы будете набирать именно эти команды.

## Форматированный вывод: fmt.Printf

`Println` хорош для быстрой печати, но часто нужно собрать строку по шаблону: вставить число в середину предложения, показать значение в нужном виде. Для этого есть `fmt.Printf`.

`Printf` принимает строку-шаблон с *глаголами форматирования* — это значки вроде `%d` или `%s`, на место которых подставляются ваши значения. Сами значения идут следующими аргументами, по порядку. Важная деталь: `Printf` **не** переводит строку автоматически, поэтому в конце шаблона обычно ставят `\n` — символ перевода строки.

Вот основные глаголы, которые покрывают почти всё на старте:

- `%d` — целое число (от *decimal*);
- `%s` — строка (от *string*);
- `%v` — значение в его «обычном» виде, подходит почти для чего угодно (от *value*);
- `%.2f` — дробное число с двумя знаками после точки (`19.989` напечатается как `19.99`);
- `%T` — тип значения, а не само значение (от *type*).

Посмотрим на `%s` и `%d` в деле:

```go play
package main

import "fmt"

func main() {
	name := "Аня"
	age := 25
	fmt.Printf("Меня зовут %s, мне %d лет.\n", name, age)
	fmt.Printf("Через год будет %d.\n", age+1)
}
```

Здесь `%s` заменился на строку `"Аня"`, а оба `%d` — на числа. Порядок подстановки строго слева направо: первый глагол берёт первый аргумент после шаблона, второй — второй, и так далее.

Если вы не уверены, какой глагол подойдёт, или просто хотите «напечатай как есть», берите `%v`. Он универсальный:

```go play
package main

import "fmt"

func main() {
	count := 7
	label := "товаров"
	price := 19.99
	fmt.Printf("В корзине %v %v на сумму %v\n", count, label, price)
}
```

`%v` напечатал и число `7`, и строку `товаров`, и дробное `19.99` — каждое в естественном виде. На практике `%v` — самый частый глагол: с него удобно начинать, а на `%d`/`%s` переходить, когда нужен контроль над форматом.

## Узнаём тип значения: %T

Поскольку Go статически типизированный, у каждого значения есть конкретный тип. Иногда полезно посмотреть на него глазами — особенно пока вы только осваиваетесь и хотите проверить себя. Для этого есть глагол `%T`.

```go play
package main

import "fmt"

func main() {
	fmt.Printf("%T\n", 42)
	fmt.Printf("%T\n", "привет")
	fmt.Printf("%T\n", 3.14)
	fmt.Printf("%T\n", true)
}
```

Вывод:

```text
int
string
float64
bool
```

Целое число имеет тип `int`, текст — `string`, дробное — `float64`, а `true`/`false` — `bool`. С этими четырьмя типами вы будете работать постоянно; подробно о них в следующей главе. Пока достаточно знать, что `%T` всегда подскажет, с чем вы имеете дело.

## Комментарии

Комментарии — это заметки в коде для людей. Компилятор их полностью игнорирует, а вы (и ваши коллеги) используете, чтобы объяснить, *почему* написано именно так. В Go два вида комментариев.

Однострочный начинается с `//` и идёт до конца строки. Многострочный заключается между `/*` и `*/`.

```go play
package main

import "fmt"

// main — точка входа в программу.
func main() {
	fmt.Println("работаем") // печатаем строку в консоль

	/*
	   А это длинное пояснение
	   на несколько строк.
	*/
}
```

Хороший комментарий объясняет замысел, а не пересказывает очевидное. Строка `i = i + 1 // увеличиваем i на единицу` бесполезна: код и так это говорит. А вот `// округляем вверх, иначе теряем копейку при делении` — полезен, потому что объясняет причину.

## Частые ошибки

- **Забыли импортировать `fmt`.** Если вы используете `fmt.Println`, но не написали `import "fmt"`, программа не соберётся: `undefined: fmt`. И наоборот: импортировали пакет, но не пользуетесь им — тоже ошибка, `"os" imported and not used`. Язык строг к неиспользуемым импортам специально, чтобы код не зарастал мусором.
- **Перепутали `Println` и `Printf`.** `Println` сам переводит строку, а `Printf` — нет. Если из `Printf` пропал перевод строки и вывод «слипся», скорее всего вы забыли `\n` в конце шаблона.
- **Глагол не совпал с аргументом.** Если написать `%d` и передать туда строку, Go не подставит её молча, но и не уронит сборку — программа соберётся и запустится, просто прямо в напечатанной строке окажется специальная пометка вида `%!d(string=привет)`. Это не падение, а сигнал «глагол и аргумент не подходят друг другу». Узнаете её — сразу поймёте, в чём дело. Когда сомневаетесь в типе, берите `%v`: он принимает что угодно.
- **Лишний или недостающий аргумент у `Printf`.** Глаголов в шаблоне должно быть ровно столько, сколько значений вы передаёте. Тут тоже не ошибка сборки, а пометка в самом выводе: лишний аргумент даёт `%!(EXTRA string=...)` в конце строки, а недостающий — `%!d(MISSING)` на месте глагола.

## Попробуйте сами

Напишите полную программу без копирования готового тела `main`. На первой строке напечатайте имя `Анна`, на второй — результат `7 + 5`. Затем одним вызовом `Printf` выведите `Имя: Анна, возраст: 18` с переводом строки. Прежде чем запускать, выпишите ожидаемые три строки.

### Проверка

Получится:

```text
Анна
12
Имя: Анна, возраст: 18
```

В теле `main` достаточно таких вызовов:

```go
fmt.Println("Анна")
fmt.Println(7 + 5)
fmt.Printf("Имя: %s, возраст: %d\n", "Анна", 18)
```

Для сборки нужны `package main`, `import "fmt"` и `func main()`. Почему в `Println` нет `\n`? Функция добавляет перевод строки сама; `Printf` использует только записанный шаблон.

## Что дальше

Печатать вы уже умеете, а значит, можете увидеть результат любой своей программы. В следующей главе — [переменные и базовые типы](/go-basics/book/variables): откуда берутся `int`, `string` и `float64`, которые сегодня мелькнули в `%T`, и как хранить значения под именами.
