Menu

go run, go build и go install: компиляция и запуск Go

Что делают go run, go build и go install, как Go называет бинарник, как собирать под другие платформы через GOOS и GOARCH и какие проверки go fmt и go vet запускать перед коммитом.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

go run компилирует и запускает программу за один шаг и не сохраняет бинарник. go build компилирует и оставляет исполняемый файл в текущей папке. go install компилирует и кладёт исполняемый файл в $HOME/go/bin. Все три команды компилируют в нативный машинный код; ни одна ничего не интерпретирует.

КомандаКомпилируетЗапускаетСохраняет бинарникКуда попадает бинарник
go run .даданетвременная папка, потом удаляется
go buildданетдатекущая папка (или -o path)
go installданетда$GOBIN, иначе $GOPATH/bin

Программа ниже используется во всех примерах этой страницы. Редактор запускает её так же, как go run.

go run

go run принимает пакет (обычно ., текущую папку) или список файлов .go:

go run .
go run main.go
go run ./cmd/server

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

go run . --port 8080 verbose
version: dev
built for: linux/amd64
args: [--port 8080 verbose]

Пишите go run ., а не go run main.go. Если указать файл, скомпилируется только он, и как только в пакете появится второй файл, объявленные там функции будут считаться undefined. Подробно эта ошибка разобрана на странице о пакетах и импортах.

go run также запускает удалённую программу конкретной версии без установки, что удобно для генераторов кода:

go run golang.org/x/tools/cmd/stringer@v0.30.0 -type=Color

go build

go build компилирует пакет в текущей папке. Для пакета main он записывает исполняемый файл; библиотечный пакет компилирует, сообщает об ошибках и выбрасывает результат.

go mod init example.com/hello
go build
ls
go.mod  hello  main.go

Имя бинарника определяется так:

Что вы запускаетеИмя бинарника
go build в модуле example.com/hellohello
go build ./cmd/serverserver
go build main.gomain (по первому файлу)
go build -o bin/app .bin/app
любой из вариантов выше с GOOS=windowsто же имя плюс .exe

Ещё две формы, которыми вы будете пользоваться постоянно:

go build ./...      # compile every package in the module
go vet ./...        # static checks, covered below

./... означает «эта папка и все папки ниже». go build ./... с несколькими пакетами main не записывает бинарники; это быстрая проверка «компилируется ли всё».

Полезные флаги сборки

ФлагЧто делает
-o nameвыходной файл или папка
-vпечатает имена пакетов по мере компиляции
-raceсборка с детектором гонок данных (медленнее, бинарник больше; для тестов)
-trimpathубирает локальные пути файловой системы из бинарника, для воспроизводимых сборок
-ldflags "-s -w"вырезает таблицу символов и отладочную информацию DWARF, бинарник становится меньше
-ldflags "-X main.version=1.4.0"задаёт строковую переменную на этапе линковки
-tags nameвключает файлы с ограничением //go:build name

Флагом -X большинство Go-проектов вшивают версию в бинарник. Он работает только с переменными типа string уровня пакета (не с константами):

go build -o app -ldflags "-X main.version=1.4.0" .
./app
version: 1.4.0
built for: linux/amd64
args: []

Бинарник также хранит версии модулей, а начиная с Go 1.18 и коммит VCS, из которого он собран. go version -m ./app их выводит, а программа может прочитать их через runtime/debug.ReadBuildInfo.

go install

go install собирает точно так же, как go build, а затем переносит исполняемый файл в $GOBIN или в $GOPATH/bin, если GOBIN не задан (по умолчанию $HOME/go/bin):

go install .
go env GOPATH

Чаще всего так устанавливают утилиты, написанные на Go. С @version программа ставится, не трогая ваш go.mod:

go install golang.org/x/tools/gopls@latest
go install honnef.co/go/tools/cmd/staticcheck@latest

Если после этого оболочка не находит утилиту, значит $HOME/go/bin нет в PATH. Добавьте export PATH=$PATH:$(go env GOPATH)/bin в профиль оболочки.

Кросс-компиляция через GOOS и GOARCH

Go умеет собирать под другую операционную систему или процессор с любой машины, без дополнительного тулчейна. Задайте для команды сборки две переменные окружения:

GOOS=linux GOARCH=amd64 go build -o app-linux-amd64 .
GOOS=linux GOARCH=arm64 go build -o app-linux-arm64 .
GOOS=darwin GOARCH=arm64 go build -o app-macos .
GOOS=windows GOARCH=amd64 go build -o app.exe .

В PowerShell переменные окружения задаются иначе:

$env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -o app-linux .

Самые частые пары:

GOOSGOARCHЦель
linuxamd64большинство серверов и контейнеров
linuxarm64AWS Graviton, Raspberry Pi с 64-битной ОС
darwinarm64Mac на Apple Silicon
darwinamd64Mac на Intel
windowsamd6464-битная Windows
jswasmWebAssembly в браузере

go tool dist list выводит все поддерживаемые пары (в Go 1.24 их 48).

Так просто кросс-компиляция работает только для кода на чистом Go. Пакету, который использует cgo (код на C, например некоторые драйверы SQLite), нужен кросс-компилятор C для целевой платформы. При кросс-компиляции cgo по умолчанию выключен, а явное CGO_ENABLED=0 к тому же даёт полностью статический бинарник для Linux, что и нужно для минимального образа контейнера scratch или distroless.

go fmt и go vet

Две проверки должны быть в любом рабочем процессе и в CI.

go fmt переписывает файлы в едином официальном стиле: табы, выровненные поля, нормализованные пробелы. Это обёртка над gofmt -l -w:

go fmt ./...
gofmt -l .     # list files that are not formatted; empty output means clean

go vet сообщает о коде, который компилируется, но почти наверняка ошибочен. Классический случай это несовпадение формата Printf:

package main

import "fmt"

func main() {
	count := 3
	fmt.Printf("%s items\n", count)
}
go vet ./...
# example.com/hello
# [example.com/hello]
./main.go:7:2: fmt.Printf format %s has arg count of wrong type int

Программа компилируется и печатает %!s(int=3) items, и именно такие баги vet и должен ловить. Среди других проверок vet: копирование sync.Mutex по значению, недостижимый код, теги структур с неправильным синтаксисом и context.CancelFunc, который так и не вызывается. go test автоматически запускает часть этих проверок; go build не запускает ни одной.

Другие подкоманды go

КомандаНазначение
go test ./...запустить тесты
go mod tidyдобавить недостающие и удалить неиспользуемые зависимости
go get pkg@versionдобавить или изменить зависимость
go clean -cacheочистить кеш сборки
go envвывести конфигурацию Go
go doc fmt.Printlnпоказать документацию в терминале
go list -m allперечислить все модули сборки

Почему повторная сборка быстрая

Go кеширует скомпилированные пакеты в кеше сборки (go env GOCACHE). При пересборке компилируются заново только пакеты, у которых изменился исходный код или зависимости, поэтому go run . на неизменённом проекте стартует почти мгновенно. Если сборка ведёт себя странно после смены версии Go или переменных окружения, go clean -cache очистит кеш; нужно это редко.

Часто задаваемые вопросы

Чем go run отличается от go build?

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

Как задать имя выходного файла в go build?

Флагом -o: go build -o myapp . запишет myapp (на Windows пишите -o myapp.exe сами). Без -o команда go build называет бинарник по последнему элементу пути импорта пакета или по первому файлу, если вы передали файлы .go, и добавляет .exe при сборке под Windows.

Как собрать Go под Linux или Windows с другой машины?

Задайте для сборки GOOS и GOARCH: GOOS=linux GOARCH=amd64 go build -o app-linux . или GOOS=windows GOARCH=amd64 go build . (получится .exe). Для кода на чистом Go дополнительный тулчейн не нужен. go tool dist list выводит все поддерживаемые пары.

Куда go install кладёт бинарник?

В $GOBIN, если переменная задана, иначе в $GOPATH/bin, то есть по умолчанию в $HOME/go/bin. Добавьте эту папку в PATH, чтобы запускать установленные утилиты по имени. go install example.com/tool@latest ставит утилиту, не добавляя её в ваш модуль.

Запускает ли go build проверку go vet?

Нет. go build только компилирует. go test автоматически запускает часть проверок go vet, но для полного набора выполните go vet ./... сами, обычно в CI рядом с gofmt -l ..

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ