Установка Go и рабочее окружение
Одно из главных обещаний Go — «инструменты в комплекте». Вам не нужно собирать зоопарк из менеджера версий, сборщика, форматтера, тест-раннера и линтера от разных вендоров, как в некоторых экосистемах. Почти всё идёт с языком в виде подкоманд go. Эта глава — про то, как получить рабочее окружение уровня продакшен-команды и не наступить на классические грабли.
Установка тулчейна
Скачайте официальный установщик с go.dev/dl. Это единственный правильный источник — не ставьте Go из системных пакетов вроде apt, они часто отстают на версии и криво настраивают пути.
# Linux: распаковать официальный архив в /usr/local
wget https://go.dev/dl/go1.24.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.24.0.linux-amd64.tar.gz
# Добавить в ~/.profile или ~/.zshrc
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$(go env GOPATH)/bin # чтобы видеть установленные через go install бинарники
# Проверить
go version
# go version go1.24.0 linux/amd64
На macOS удобнее взять .pkg с того же сайта, на Windows — .msi. brew install go тоже работает, но помните: Homebrew отдаёт вам версию по своему расписанию.
Управление версиями Go
Начиная с Go 1.21 тулчейн умеет сам подтягивать нужную версию. Если в go.mod написано go 1.24.0, а у вас установлен 1.22, команда go при необходимости скачает и использует правильный тулчейн. Директива toolchain в go.mod управляет этим явно. Для параллельной установки нескольких версий есть официальный способ:
go install golang.org/dl/go1.23.0@latest
go1.23.0 download
go1.23.0 version
Раньше в ходу были сторонние менеджеры (gvm, asdf), но со встроенным механизмом тулчейна они почти не нужны.
GOPATH ушёл, пришли модули
Историческая справка, без которой вы не поймёте старые статьи. До версии 1.11 весь код Go жил внутри одной директории $GOPATH/src, а импорты привязывались к пути на диске. Это было мучительно: проект нельзя было положить куда угодно, вендоринг был кошмаром. Модули (Go modules) появились в 1.11 и стали стандартом по умолчанию с 1.16. Сегодня GOPATH — это лишь кеш скачанных модулей ($GOPATH/pkg/mod) и место для бинарников ($GOPATH/bin). Забудьте про необходимость держать код внутри GOPATH.
go.mod и go.sum — сердце проекта
Проект на Go начинается с модуля:
mkdir myservice && cd myservice
go mod init github.com/acme/myservice
Это создаёт go.mod:
module github.com/acme/myservice
go 1.24.0
require (
github.com/go-chi/chi/v5 v5.1.0
github.com/jackc/pgx/v5 v5.7.1
)
module— канонический путь импорта. По нему другие проекты будут вас импортировать, поэтому обычно это URL репозитория.go— минимальная версия языка/тулчейна.require— прямые зависимости с точными версиями (семантическое версионирование).
go.sum — это не список зависимостей, а список криптографических хешей каждой версии каждого модуля (включая транзитивные). При сборке Go сверяет скачанное с этими хешами. Если кто-то подменит содержимое версии в репозитории — сборка упадёт. Оба файла обязательно коммитятся в git. Это ваша защита цепочки поставок.
Основные команды работы с зависимостями:
go get github.com/go-chi/chi/v5@v5.1.0 # добавить/обновить конкретную зависимость
go get -u ./... # обновить зависимости до свежих минорных
go mod tidy # привести go.mod/go.sum в порядок: убрать лишнее, дописать нужное
go mod download # скачать всё в кеш (полезно в Docker-слое)
go mod verify # проверить целостность кеша
go mod why github.com/x/y # объяснить, зачем эта зависимость в графе
go mod tidy стоит запускать перед каждым коммитом, меняющим зависимости, — он гарантирует, что go.mod описывает ровно то, что реально используется.
Прокси, приватные модули и безопасность
По умолчанию Go качает модули через публичный прокси proxy.golang.org и сверяет их с checksum database sum.golang.org — это прозрачный лог, защищающий от подмены. Настраивается через переменные окружения:
go env -w GOPROXY=https://proxy.golang.org,direct
go env -w GOPRIVATE=github.com/acme/* # приватные модули: не ходить в прокси и checksum-базу
go env -w GONOSUMCHECK=off # НЕ отключайте проверку сумм без веской причины
Для корпоративной разработки часто поднимают собственный прокси (Athens, Artifactory) — он кеширует зависимости и переживает удаление публичных репозиториев.
Форматирование: gofmt — закон
gofmt (и его надстройка goimports) — культурный столп Go. Один канонический стиль, ноль споров. Никогда не форматируйте Go вручную.
gofmt -w . # переформатировать всё на месте
go fmt ./... # то же через обёртку go
goimports дополнительно сортирует и чистит блок импортов, добавляя недостающие и убирая неиспользуемые:
go install golang.org/x/tools/cmd/goimports@latest
goimports -w .
Настройте автозапуск goimports при сохранении в редакторе — и вы больше никогда не подумаете об импортах и отступах.
go vet и статический анализ
go vet встроен в тулчейн и ловит подозрительные конструкции, которые компилируются, но почти наверняка баги: неправильные строки формата в Printf, копирование структур с мьютексами, недостижимый код, ошибки в тегах структур.
go vet ./...
go vet — минимум, который должен быть зелёным всегда. Но для продакшена его недостаточно. Стандарт индустрии — golangci-lint: агрегатор десятков линтеров, запускаемых за один проход.
# установка (см. golangci-lint.run)
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run ./...
Конфигурация в .golangci.yml в корне проекта:
run:
timeout: 5m
linters:
enable:
- errcheck # непроверенные ошибки
- govet # то же, что go vet
- staticcheck # мощнейший анализатор, ловит реальные баги
- revive # замена golint, стилистика
- gosimple # упрощения кода
- ineffassign # бессмысленные присваивания
- unused # мёртвый код
- gocritic # диагностики и советы по стилю
- bodyclose # незакрытые resp.Body
- errorlint # правильная работа с обёрнутыми ошибками (Is/As)
issues:
exclude-rules:
- path: _test\.go
linters:
- errcheck
Отдельно стоит упомянуть staticcheck (dominikh.se) — вероятно, лучший статический анализатор для Go, он входит в golangci-lint, но его можно ставить и запускать отдельно. Не спорьте с ним: почти всегда он прав.
LSP и редактор
Официальный языковой сервер — gopls (произносится «go please»). Он даёт автодополнение, переход к определению, рефакторинги, инлайн-диагностику. Ставится и обновляется так:
go install golang.org/x/tools/gopls@latest
- VS Code: официальное расширение «Go» от команды Go — само предложит доставить gopls, dlv (отладчик), goimports.
- GoLand от JetBrains — мощная коммерческая IDE, для больших проектов часто удобнее.
- Neovim/Vim/Emacs — через встроенный LSP-клиент и gopls.
Отладчик — delve (dlv), нативный для Go, понимает горутины:
go install github.com/go-delve/delve/cmd/dlv@latest
dlv debug ./cmd/server
Раскладка проекта (project layout)
У Go нет навязанной структуры каталогов, но сложились конвенции. Есть популярный репозиторий golang-standards/project-layout — но важная оговорка: это не официальный стандарт, и команда Go его не поддерживает. Для маленького проекта он избыточен. Начинайте с плоской структуры и усложняйте по мере роста.
Прагматичный layout для сервиса среднего размера:
myservice/
├── go.mod
├── go.sum
├── Makefile
├── .golangci.yml
├── cmd/ # точки входа (main-пакеты)
│ └── server/
│ └── main.go
├── internal/ # приватный код, недоступный извне модуля
│ ├── config/
│ ├── http/ # хендлеры, роутер, middleware
│ ├── service/ # бизнес-логика
│ ├── storage/ # работа с БД
│ └── domain/ # доменные типы
├── pkg/ # код, который МОЖНО импортировать извне (если нужно)
├── migrations/ # SQL-миграции
└── api/ # OpenAPI/proto спецификации
Ключевой механизм — каталог internal/. Это не соглашение, а правило компилятора: пакеты внутри internal/ может импортировать только код из того же модуля (точнее, из поддерева над internal). Это способ на уровне языка запретить внешним потребителям завязываться на ваши кишки. Используйте internal/ щедро — по умолчанию весь код сервиса кладите туда, а в pkg/ выносите только то, что осознанно делаете публичным API.
Каталог cmd/ держит main-пакеты: по одному подкаталогу на каждый собираемый бинарник (cmd/server, cmd/migrator, cmd/cli). Сама точка входа должна быть тонкой — собрать зависимости и передать управление в internal.
Makefile как единая точка входа
Команды длинные, их легко забыть. Заверните их в Makefile — это де-факто стандарт для локальной автоматизации:
.PHONY: fmt lint test build run
fmt:
goimports -w .
gofmt -w .
lint:
golangci-lint run ./...
test:
go test -race -cover ./...
build:
CGO_ENABLED=0 go build -o bin/server ./cmd/server
run:
go run ./cmd/server
Полезные подкоманды go, которые стоит знать
go run ./cmd/server # скомпилировать и сразу запустить
go build ./... # собрать всё, проверить компиляцию
go test ./... # прогнать тесты
go doc fmt.Println # документация по символу прямо в терминале
go env # посмотреть все переменные окружения тулчейна
go clean -cache # почистить кеш сборки при странных ошибках
go install ./cmd/cli # собрать и положить бинарник в $GOPATH/bin
Итоговый чек-лист рабочего окружения
- Go установлен с go.dev/dl,
go versionработает. -
$GOPATH/binвPATH. - Редактор с gopls, форматирование
goimportsпри сохранении. - В проекте
go.modиgo.sumпод контролем версий. -
.golangci.ymlнастроен,golangci-lint runзелёный. -
Makefileсfmt/lint/test/build. -
internal/для приватного кода, тонкийcmd/.
Что дальше
Окружение готово. Пора писать код — разберём синтаксис, систему типов и модель памяти Go.