Командная строка

Команды Go включают полный набор инструментов, охватывающих документацию, форматирование, проверку кода, компиляцию, тестирование, управление зависимостями и другие аспекты — практически всё, что связано с разработкой на Go.
bug сообщить об уязвимости
build компиляция пакетов и зависимостей
clean удаление объектных файлов
doc отображение документации из исходного кода
env просмотр информации о переменных среды Go
fix исправление проблем совместимости API из-за изменений версии go
fmt форматирование исходного кода
generate генерация кода
get добавление зависимостей
install установка и компиляция пакетов
list команда списка пакетов/модулей
mod команда обслуживания модулей
work команда обслуживания рабочего пространства
run компиляция и запуск
test тестирование
tool запуск указанного инструмента go
version отображение информации о версии go
vet сканирование и вывод возможных проблем в исходном кодеЭта статья лишь кратко описывает и знакомит с их использованием. Весь контент основан на официальной документации. Для получения более подробной информации вы можете обратиться к cmd/go.
help
Первая команда, которую нужно знать — это help, с её помощью можно прочитать инструкции по использованию команд. Есть два способа использования: если нужна краткая информация, можно добавить флаг -h после указанной команды, например
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Go кратко покажет использование этой команды. Он также подсказывает, что для получения более подробной информации нужно использовать команду help
$ go help env
usage: go env [-json] [-u] [-w] [var ...]
Env prints Go environment information.
By default env prints information as a shell script
(on Windows, a batch file). If one or more variable
names is given as arguments, env prints the value of
each named variable on its own line.
The -json flag prints the environment in JSON format
instead of as a shell script.
The -u flag requires one or more arguments and unsets
the default setting for the named environment variables,
if one has been set with 'go env -w'.
The -w flag requires one or more arguments of the
form NAME=VALUE and changes the default settings
of the named environment variables to the given values.
For more about environment variables, see 'go help environment'.Используйте команду help разумно — с её помощью вы можете получить много информации о командах.
doc
$ go doc -h
Usage of [go] doc:
go doc
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
go doc <pkg> <sym>[.<methodOrField>]
For more information run
go help doc
Flags:
-C dir
change to dir before running command
-all
show all documentation for package
-c symbol matching honors case (paths not affected)
-cmd
show symbols with package docs even if package is a command
-short
one-line representation for each symbol
-src
show source code for symbol
-u show unexported symbols as well as exportedКоманда doc выводит комментарии документации для указанного пакета, константы, функции, типа, переменной, метода и даже полей структуры. Без параметров она выводит комментарии текущего пакета
$ go docТакже можно указать конкретный пакет, например, посмотреть комментарии документации пакета runtime
$ go doc runtime
package runtime // import "runtime"
Package runtime contains operations that interact with Go's runtime system,
such as functions to control goroutines. It also includes the low-level type
information used by the reflect package; see reflect's documentation for the
programmable interface to the run-time type system.
......Или определённый тип
$ go doc unsafe.Pointer
package unsafe // import "unsafe"
type Pointer *ArbitraryType
Pointer represents a pointer to an arbitrary type. There are four special
operations available for type Pointer that are not available for other
types:
- A pointer value of any type can be converted to a Pointer.
- A Pointer can be converted to a pointer value of any type.
- A uintptr can be converted to a Pointer.
- A Pointer can be converted to a uintptr.
...Или определённую функцию
$ go doc runtime.GC
package runtime // import "runtime"
func GC()
GC runs a garbage collection and blocks the caller until the garbage
collection is complete. It may also block the entire program.Она имеет следующие часто используемые флаги
-u: просмотр приватных типов-all: просмотр всей документации указанного пакета-short: только краткое однострочное описание-src: вывод исходного кода-cmd: для пакетов, относящихся к командам go, также выводить документацию кода внутри пакета
Например, просмотр переменной runtime.inf, которая не экспортируется
$ go doc -u runtime.inf
package runtime // import "runtime"
var inf = float64frombits(0x7FF0000000000000)Используйте команду doc разумно, чтобы вам было удобнее читать документацию.
Другой способ читать документацию команд — читать исходный код, потому что документация некоторых команд может быть не такой подробной, а в исходном коде могут быть более детальные пояснения. Поскольку все эти команды написаны на Go, их удобно читать. Все команды находятся в пакете src/cmd, каждый подпакет — это отдельная команда, точка входа находится в файле cmd/go/main.go
func init() {
base.Go.Commands = []*base.Command{
bug.CmdBug,
work.CmdBuild,
clean.CmdClean,
doc.CmdDoc,
envcmd.CmdEnv,
fix.CmdFix,
fmtcmd.CmdFmt,
generate.CmdGenerate,
modget.CmdGet,
work.CmdInstall,
list.CmdList,
modcmd.CmdMod,
workcmd.CmdWork,
run.CmdRun,
test.CmdTest,
tool.CmdTool,
version.CmdVersion,
vet.CmdVet,
help.HelpBuildConstraint,
help.HelpBuildmode,
help.HelpC,
help.HelpCache,
help.HelpEnvironment,
help.HelpFileType,
modload.HelpGoMod,
help.HelpGopath,
get.HelpGopathGet,
modfetch.HelpGoproxy,
help.HelpImportPath,
modload.HelpModules,
modget.HelpModuleGet,
modfetch.HelpModuleAuth,
help.HelpPackages,
modfetch.HelpPrivate,
test.HelpTestflag,
test.HelpTestfunc,
modget.HelpVCS,
}
}Здесь вы найдёте все подкоманды go, а также информацию об их справочной документации.
bug
$ go help bug
usage: go bug
Bug opens the default browser and starts a new bug report.
The report includes useful system information.Эта команда не имеет никаких параметров и флагов. Она открывает браузер по умолчанию и переходит на страницу issue репозитория github.com/golang/go, чтобы вы могли сообщить об ошибке. Кроме этого, она не имеет никакого другого применения.
version
С помощью команды version можно узнать текущую версию Go.
$ go version -h
usage: go version [-m] [-v] [file ...]При выполнении без параметров она выводит текущую версию языка Go
$ go version
go version go1.21.0 windows/amd64Она также принимает путь к файлу в качестве параметра и выводит версию Go, использованную при компиляции всех распознаваемых двоичных файлов по этому пути.
$ go version -v ./
buf.exe: go1.20.2
cobra-cli.exe: go1.21.0
dlv.exe: go1.20.2
goctl.exe: go1.20.2
goimports.exe: go1.20.2
golangci-lint.exe: go1.20.2
gopls.exe: go1.19.3
kratos.exe: go1.20.2
main.exe: go1.19.1
protoc-gen-go-grpc.exe: go1.20.2
protoc-gen-go-http.exe: go1.20.2
protoc-gen-go.exe: go1.20.2
protoc-gen-openapi.exe: go1.20.2
swag.exe: go1.21.0
wire.exe: go1.21.0Параметр -v указывает команде version пытаться выводить версию Go для нераспознаваемых файлов. Параметр -m выводит информацию о модулях двоичного файла, а также некоторые параметры компиляции. Ниже приведён простой пример.
$ go version -v -m wire.exe
wire.exe: go1.21.0
path github.com/google/wire/cmd/wire
mod github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
dep github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
dep github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
dep golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s=
build -buildmode=exe
build -compiler=gc
build DefaultGODEBUG=panicnil=1
build CGO_ENABLED=1
build CGO_CFLAGS=
build CGO_CPPFLAGS=
build CGO_CXXFLAGS=
build CGO_LDFLAGS=
build GOARCH=amd64
build GOOS=windows
build GOAMD64=v1Сам go также является двоичным файлом. На самом деле, при выполнении без параметров go version выводит версию самого себя, потому что весь инструментарий cmd/go реализован на самом Go.
env
С помощью команды env можно просмотреть информацию обо всех переменных среды Go. Изменение этих переменных среды повлияет на поведение инструментария Go.
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.При выполнении без параметров команда выводит значения всех переменных среды Go
$ go env
set GO111MODULE=on
set GOARCH=amd64
...Указав имя переменной среды в качестве параметра, можно вывести значение только этой переменной
$ go env GO111MODULE
onДобавьте -json, чтобы вывести в формате JSON
$ go env -json
{
"AR": "ar",
"CC": "gcc",
......
}С помощью флага -w и параметра в формате var=value можно навсегда изменить значение переменной
$ go env -w GO111MODULE=onИспользуя флаг -u, можно вернуть переменную к значению по умолчанию
$ go env -u GO111MODULEВыполните go help environment, чтобы увидеть описание каждой переменной среды
$ go help environment
The go command and the tools it invokes consult environment variables
for configuration. If an environment variable is unset or empty, the go
command uses a sensible default setting. To see the effective setting of
the variable <NAME>, run 'go env <NAME>'. To change the default setting,
run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
are recorded in a Go environment configuration file stored in the
per-user configuration directory, as reported by os.UserConfigDir.
...Ниже представлены некоторые часто используемые переменные среды
GOVERSION
Значение этой переменной среды зависит от версии Go, а номер версии берётся из файла $GOROOT/VERSION, который содержит текущий номер версии Go и время сборки.
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35ZЗначение переменной runtime.Version совпадает со значением GOVERSION, и эта переменная среды не может быть изменена.
GOENV
В каталоге $GOROOT есть конфигурационный файл по умолчанию с именем go.env
$ cat $GOROOT/go.env
# This file contains the initial defaults for go command configuration.
# Values set by 'go env -w' and written to the user's go/env file override these.
# The environment overrides everything else.
# Use the Go module mirror and checksum database by default.
# See https://proxy.golang.org for details.
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/doc/toolchain for details.
GOTOOLCHAIN=autoЕго формат — простая форма key=value. Значения переменных среды, изменённые командой go env -w key=value, будут записаны в конфигурационный файл. Однако можно не использовать конфигурационный файл по умолчанию — переменная среды GOENV позволяет вручную указать адрес конфигурационного файла env, и значение переменной среды GOENV может быть переопределено только переменной среды операционной системы и не может быть изменено командой go env -w.
GOHOSTARCH
Представляет архитектуру CPU данного компьютера, используется только для отображения. Значение этой переменной среды не считывается из конфигурационного файла и не может быть изменено.
GOHOSTOS
Представляет операционную систему данного компьютера, используется только для отображения. Значение этой переменной среды не считывается из конфигурационного файла и не может быть изменено.
GOOS
При компиляции значение GOOS определяет, в какой целевой системе будет скомпилирован двоичный файл из исходного кода. Значение по умолчанию — GOHOSTOS, то есть операционная система данного компьютера. Доступные значения:
linuxdarwinwindowsnetbsdaixandroid
Фактически поддерживаемых операционных систем больше. Используйте команду go tool dist list, чтобы посмотреть все поддерживаемые значения
$ go tool dist list | awk -F '/' '{print $1}' | awk '!seen[$0]++'
aix
android
darwin
dragonfly
freebsd
illumos
ios
js
linux
netbsd
openbsd
plan9
solaris
wasip1
windowsGOARCH
При компиляции значение GOARCH определяет, какой набор инструкций архитектуры CPU будет использоваться при компиляции. Значение по умолчанию — GOHOSTARCH, то есть архитектура CPU данного компьютера. Доступные значения:
amd64386armppc64
Фактически поддерживаемых архитектур больше. Используйте команду go tool dist list, чтобы посмотреть все поддерживаемые значения
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390xОбратите внимание, что GOOS и GOARCH нельзя комбинировать произвольно — некоторые операционные системы поддерживают только определённые архитектуры CPU.
GOROOT
GOROOT представляет корневой каталог установки языка Go. Значение GOROOT не может быть изменено напрямую и может быть переопределено только переменной среды операционной системы.
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSIONВ корневом каталоге есть несколько важных папок и файлов
lib— хранит некоторые зависимости. На данный момент там только библиотека с информацией о часовых поясах разных стран, расположенная в$GOROOT/lib/time. Скомпилированный двоичный файл не будет содержать эту информацию о часовых поясах.pkg— хранит некоторые библиотеки инструментов и заголовочные файлы. Например, командаgo toolищет двоичные файлы инструментария Go в каталоге$GOROOT/pkg/toolbin— хранит двоичные файлы. По умолчанию там только два исполняемых файла:goиgofmt. Каталог$GOROOT/binдолжен быть добавлен в системные переменные, иначе вы не сможете использовать команду go.src— хранит исходный код GoVERSION— этот файл содержит информацию о версии языка Gogo.env— этот файл является конфигурационным файломenvпо умолчанию
GOPATH
Значение GOPATH по умолчанию — $HOME/go. Эта переменная среды указывает, где искать импортируемые файлы при разборе операторов import. В ранние времена, когда не было gomod, GOPATH использовался специально для хранения различных сторонних библиотек. Его структура выглядела так:
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)После появления gomod, GOPATH стал просто местом для хранения зависимостей, загруженных go get, и двоичных файлов, загруженных и скомпилированных go install. Обратите внимание, что расположение GOPATH не может совпадать с GOROOT, иначе это не будет иметь никакого эффекта.
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effectНа момент написания этой статьи версия Go уже достигла 1.21.3. За исключением очень старых проектов, практически никто больше не использует gopath для управления зависимостями.
GOBIN
GOBIN используется для хранения загруженных и скомпилированных сторонних двоичных исполняемых файлов go install. Значение по умолчанию — $GOPATH/bin. Как и $GOROOT/bin, этот каталог должен быть добавлен в переменные среды операционной системы, иначе вы не сможете использовать двоичные файлы в каталоге GOBIN.
GOMODCACHE
GOMODCACHE указывает место хранения зависимостей, загруженных go get. Значение по умолчанию — $GOPATH/pkg/mod. Формат хранения:
$GOMODCACHE/domain/username/project@verionВ том же каталоге также будет папка с именем sumdb для хранения информации, связанной с базой данных контрольных сумм зависимостей.
GOCACHE
Хранит кэшированную информацию для компиляции. Значение по умолчанию — $HOME/.cache/go-build. В этом каталоге будет создан файл README.
$ cat $(go env GOCACHE)/README
This directory holds cached build artifacts from the Go build system.
Run "go clean -cache" if the directory is getting too large.
Run "go clean -fuzzcache" to delete the fuzz cache.
See golang.org to learn more about Go.Каждая сборка build создаёт множество файлов, и Go кэширует эти файлы для повторного использования при следующей компиляции.
GOTEMPDIR
Используется для временных файлов, создаваемых во время компиляции, например, временных двоичных файлов, которые запускает go run. Значение по умолчанию — временный каталог, указанный операционной системой: на Mac или Linux это /tmp, на Windows — %TEMP%. Также можно изменить на указанный пользователем путь.
GO111MODULE
Эта переменная среды указывает, какой способ использовать для управления зависимостями проекта Go. Доступны три значения:
off— отключить gomod, использовать gopath, и игнорировать все файлыgo.modon— использовать gomod, не использовать gopath (по умолчанию)auto— автоматическое определение: если проект содержит файлgo.mod, будет использоваться gomod
TIP
Почему называется GO111MODULE, а не просто GOMODULE? Потому что gomod был впервые представлен в версии Go 1.11.
GOPROXY
Прокси модулей Go. Значение по умолчанию — https://proxy.golang.org,direct. URL-адреса разделяются запятыми. direct означает прямое использование VCS, минуя прокси модулей — это выполняется только если первый недоступен. Также доступен вариант off, который запрещает загрузку любых модулей. Кроме того, GOPROXY может быть путём к файлу, например:
GOPROXY=file://$(go env GOMODCACHE)/cache/downloadЧерез go get -x можно посмотреть команды, выполняемые в процессе загрузки зависимостей, и узнать, используется ли прокси.
$ go get -x github.com/spf13/cast
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/spf13/cast/@v/list
...Использование прокси модулей может эффективно ускорить загрузку модулей. Пользователи в Китае практически не могут получить доступ к официальному прокси по умолчанию без использования прокси. В настоящее время доступны следующие публичные и заслуживающие доверия сторонние прокси модулей:
https://proxy.golang.com.cn—开源, также предоставляет корпоративную версиюhttps://goproxy.cn— предоставлен и открыт Qiniu Cloud
Конечно, есть также решения с собственным прокси модулей с открытым исходным кодом: goproxy
GOSUMDB
GOSUMDB используется для установки адреса базы данных контрольных сумм библиотек зависимостей. По умолчанию — sum.golang.org. Когда вы устанавливаете прокси, Go будет обращаться к базе данных контрольных сумм через прокси.
GOPRIVATE
Переменная среды GOPRIVATE используется для установки приватных библиотек. Соответствующие библиотеки не будут проверяться через sumdb и не будут использовать прокси — зависимости будут загружаться напрямую через VCS. Поддерживает шаблоны, разделяется запятыми. Например, все зависимости с суффиксом corp.example.com и github.com/gohper/myproject не будут использовать прокси и sumdb:
GOPRIVATE=*.corp.example.com,github.com/gohper/myprojectМожно также указать определённого пользователя или организацию:
GOPRIVATE=github.com/gopher,github.com/myorganizationGONOPROXY
Указывает, какие зависимости не должны использовать прокси. Правила такие же, как у GOPRIVATE, и переопределяет GOPRIVATE.
GONOSUMDB
Указывает, какие зависимости не должны использовать базу данных контрольных сумм. Правила такие же, как у GOPRIVATE, и переопределяет GOPRIVATE.
GOINSECURE
Указывает, какие зависимости загружать напрямую через VCS. Правила такие же, как у GOPRIVATE, и переопределяется GONOPROXY и GONOSUMDB.
GOVCS
Устанавливает систему контроля версий для управления модулями. По умолчанию public:git|hg,private:all. Можно ограничить VCS для определённых доменов, например:
GOVCS=github.com:git,evil.com:off,*:git|hgВ указанном ограничении github может использовать только git, evil.com не разрешено, | означает несколько VCS. Если не накладывать никаких ограничений:
GOVCS=*:allЕсли запретить использование любого VCS:
GOVCS=*:offGOWORK
Устанавливает, включено ли рабочее пространство. По умолчанию пусто — включено. Если установить off, то рабочее пространство не используется, и все файлы go.work игнорируются.
GOTOOLDIR
Устанавливает расположение инструментария Go. По умолчанию $GOROOT/pkg/tool, там же хранится инструментарий по умолчанию.
GODEBUG
Устанавливает параметры отладки в формате ключ-значение для управления некоторым поведением выполнения Go-программы, например:
GODEBUG=http2client=0,http2server=0Эти настройки предназначены для упрощения отката к старому поведению при появлении несовместимых изменений в процессе обновления версий. Например, в версии 1.21 больше не разрешается panic(nil). Для этого Go официально ведёт GODEBUG History — перейдите на GODEBUG для получения дополнительной информации.
CGO_ENABLED
Указывает, включён ли cgo. По умолчанию 1 — включён. Установите 0 для отключения.
Выше перечислены наиболее часто используемые переменные среды. Для менее часто используемых не приводится подробное описание, например, CGO, WASM и т.д. — вы можете изучить их самостоятельно.
build
Go поддерживает два компилятора: gccgo и gc. gcc — это старый компилятор C/C++, поддерживающий множество языков, включая Go. Последний, gc, не означает garbage collection — это сокращение от go compiler. Go завершил самостоятельную компиляцию в версии 1.5. gc — это компилятор, полностью написанный на Go, его исходный код находится в пакете cmd/compile. Поскольку он полностью реализован на Go, его удобно изучать и понимать внутренние механизмы. По умолчанию компилятор использует gc для компиляции. Кстати, отладчик Go также бывает двух типов: gdb и dlv. Первый — старый отладчик C/C++, поддерживающий множество языков, включая Go. Второй — отладчик, написанный на Go, с более дружественной поддержкой языка Go. Он также имеет открытый исходный код. Рекомендуется использовать второй.
Команда build компилирует исходные файлы Go в исполняемые двоичные файлы. Вы получите очень быстрый опыт компиляции — это одна из особенностей языка Go.
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.Она принимает три параметра: путь вывода файла, указанный флагом -o, флаги сборки build flags для определения поведения компиляции, и пакет для компиляции — этот параметр должен быть последним. Ниже приведён простой пример без использования флагов сборки.
# Windows
$ go build -o .\bin\golearn.exe golearn
# macOS / Linux
$ go build -o ./bin/golearn golearn./bin/golearn.exe — это путь вывода, golearn — модуль для компиляции. Также может быть входным файлом или папкой. Например, следующий простой пример использует main.go в качестве входного файла для компиляции.
# Windows
$ go build -o .\bin\golearn.exe main.go
# macOS / Linux
$ go build -o ./bin/golearn main.goПри компиляции будут проигнорированы все файлы, оканчивающиеся на _test.go, потому что по соглашению это тестовые файлы.
Кроме того, команда build поддерживает множество флагов сборки для контроля поведения при компиляции.
-x: выводить подробные инструкции в процессе компиляции-n: аналогично-x, но только выводит инструкции, не выполняя их-v: выводить компилируемые пакеты-p: количество параллельных процессов при компиляции-a: принудительная пересборка, даже если всё актуально-compiler: указать, какой компилятор использовать —gccgoилиgc. Последний — компилятор, написанный на Go.-race: включить обнаружение гонок данных-msan: включить анализ памяти-asan: включить анализ адресов-cover: включить обнаружение покрытия кода-buildmode: указать режим компиляции:archive,c-archive,c-shared,default,shared,exe,pie,plugin-pgo: указать файл pgo-trimpath: убрать префикс пути исходных файлов. Время компиляции заметно увеличится, примерно на 20-40%, в зависимости от количества файлов.-toolexec: выполнить некоторые команды Go перед компиляцией, формат-toolexec 'cmd args'-gcflags: указать теги для компилятора gc-gccgoflags: указать теги для компилятора gccgo-ldflags: указать теги для инструмента link
Для некоторых параметров, таких как ldflags, можно передать "-help", чтобы увидеть возможные значения, например:
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
......Это наиболее часто используемые параметры. Остальные, не так часто используемые, можно изучить самостоятельно.
gcflags
С помощью gcflags можно передать компилятору gc некоторые параметры для управления определённым поведением. Формат использования: -gcflags="pattern=args list". args list — это список параметров, pattern — область действия. Доступны следующие значения:
main— путь к пакету верхнего уровня, где находится входной файлall— текущий модуль и все зависимости текущего режимаstd— стандартная библиотекаcmd— все исходные файлы в пакетеcmd- Шаблоны, например
.,./...,cmd/...
Это правило pattern применимо ко всем флагам, поддерживающим этот формат, например ldflags. Используйте следующую команду, чтобы просмотреть доступные значения параметров:
$ go build -gcflags -help
usage: compile [options] file.go...
-% debug non-static initializers
-+ compiling runtime
-B disable bounds checking
...Ниже приведены несколько часто используемых параметров:
-S: выводить код в форме ассемблера-N: отключить оптимизацию компиляции-m: выводить решения об оптимизации-l: отключить инлайнинг функций-c: количество параллельных потоков компиляции-dwarf: генерировать флаги DWARF
Например, чтобы посмотреть ассемблерный вид кода, используйте параметр -S. Также нужно отключить оптимизацию и инлайнинг, чтобы восстановить исходную форму:
$ go build -trimpath -gcflags="-N -l -S" main.go
main.main STEXT size=171 args=0x0 locals=0x58 funcid=0x0 align=0x0
0x0000 00000 (./main.go:9) TEXT main.main(SB), ABIInternal, $88-0
...ldflags
С помощью ldflags можно передать компоновщику некоторые параметры для управления определённым поведением. Используйте следующую команду, чтобы посмотреть все доступные значения ldflags — их около двух-трёх десятков.
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
...Параметр -X в ldflags — очень полезная функция. Он позволяет определить значение строковой переменной указанного пакета во время компоновки. С помощью этой функции можно удобно внедрять метаданные во время компиляции. И это просто переменная, поэтому её легко получить во время выполнения. Вот простой пример:
package main
import "fmt"
var (
Version string
)
func main() {
fmt.Println(Version)
}Выполните команду:
go build -ldflags "-X main.Version=$(git describe --always)" main.goПосле запуска будет выведена контрольная сумма SHA1 коммита git:
5e3fd7aДругие полезные параметры:
-w: не генерировать DWARF — информацию для отладки исходного кода-s: отключить таблицу символов
Эти два параметра часто используются вместе и могут значительно уменьшить размер скомпилированного двоичного файла — примерно на 40-50%. Недостаток очевиден — невозможность отладки. Пример:
$ go build -ldflags="-w -s" main.goКросс-компиляция
Компиляция Go имеет два основных преимущества: первое — скорость, второе — кросс-компиляция. Кросс-компиляция означает возможность компиляции в целевой код для других систем локально, например, на windows можно скомпилировать двоичные файлы для linux или darwin, и наоборот. Кросс-компиляция поддерживается многими языками, это не новинка, но кросс-компиляция Go очень проста — достаточно выполнить два шага:
- Установить переменную среды GOOS, выбрать целевую операционную систему
- Установить переменную среды GOARCH, выбрать целевую архитектуру CPU
- Компилировать с помощью
go buildкак обычно
Весь процесс очень короткий, не требует дополнительных инструментов или конфигурации, и скорость такая же быстрая. Пример:
build_linux:
SET CGO_ENABLED=0
SET GOOS="linux"
SET GOARCH="amd64"
go build -o golearn main.go
build_mac:
SET CGO_ENABLED=0
SET GOOS="darwin"
SET GOARCH="amd64"
go build -o golearn main.go
build_win:
SET CGO_ENABLED=0
SET GOOS="win"
SET GOARCH="amd64"
go build -o golearn.exe main.go
.PHONY: build_linux \
build_mac \
build_winПервый шаг SET CGO_ENABLED=0 отключает cgo. Как только ваш код использует cgo, кросс-компиляция не будет работать нормально. Второй шаг SET GOOS устанавливает целевую систему: linux, darwin, windows, netbsd. Третий шаг устанавливает архитектуру CPU SET GOARCH: amd64, 386, arm, ppc64. Последний шаг — компиляция как обычно.
Управление компиляцией
Команда build может управлять компиляцией с помощью tags. Они существуют в исходном коде в виде директив. Рассмотрим пример, файл product.go:
// +build product
package main
import "fmt"
func main() {
fmt.Println("product")
}Файл debug.go:
// +build debug
package main
import "fmt"
func main() {
fmt.Println("debug")
}Оба имеют директиву // +build, указывающую, при каких условиях они будут скомпилированы. Основной формат:
// +build tag1 tag2
package pkg_nameЕсть несколько обязательных правил:
- Между
//и+buildдолжен быть пробел - Она должна находиться над объявлением пакета
- Между ней и объявлением пакета должна быть пустая строка
Кроме того, с помощью простых разделителей можно реализовать логическое управление: пробел означает OR, запятая означает AND, ! означает NOT. Пример:
// +build windows linux
package pkg_nameОзначает, что на платформе windows или linux текущий файл будет скомпилирован.
// +build windows,amd64,!cgo linux,i386,cgo
package pkg_nameЭтот пример означает, что файл будет скомпилирован только на платформе windows с архитектурой amd64 и без cgo, или на платформе linux с архитектурой i386 и с cgo. Если вы просто не хотите, чтобы файл участвовал в компиляции, используйте ignore:
// +build ignore
package pkg_nameТакже могут быть многострочные директивы:
// +build windows
// +build amd64
package pkg_nameМногострочные директивы обрабатываются как AND. Для тегов платформы и архитектуры go автоматически передаёт их при компиляции. Мы также можем передавать пользовательские теги. Возьмём два файла из начала:
$ go build -tags="debug" . && ./golearn.exe
debug
$ go build -tags="product" . && ./golearn.exe
productВидно, что при передаче разных тегов вывод отличается — цель управления компиляцией достигнута.
run
Команда run аналогична build — обе компилируют исходный код. Разница в том, что run после компиляции сразу запускает программу. Команда run не генерирует отладочную информацию для ускорения компиляции, поэтому не поддерживает отладку, и создаёт только временный двоичный файл, обычно в каталоге GOTMEPDIR, например /temp/go-build2822241271/b001/exe/main.exe.
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.Она также поддерживает флаги сборки команды build, а также предоставляет параметр -exec для указания, какая программа будет запускать двоичный файл. [arguments...] — это аргументы запуска программы. Пример:
package main
import (
"fmt"
"os"
)
var (
Version string
)
func main() {
fmt.Println(Version)
fmt.Println(os.Args[1:])
}Используйте go run для запуска:
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]В целом использование аналогично go build, поэтому подробно не описывается.
tool
Команда tool сама по себе не имеет функций, её роль — напрямую вызывать инструменты в каталоге cmd/. Например, cmd/compile — встроенный компилятор. Через go tool можно напрямую вызывать эти инструменты без необходимости вручную запускать их двоичные файлы.
$ go tool -h
usage: go tool [-n] command [args...]Используйте параметр -n, чтобы вывести все поддерживаемые команды:
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vetЭти инструменты хранятся в каталоге GOROOT/pkg/tool, сгруппированы по операционной системе и архитектуре CPU:
$ ls $GOROOT/pkg/tool/windows_amd64/ -1
addr2line.exe*
asm.exe*
buildid.exe*
cgo.exe*
compile.exe*
...Используйте формат go doc cmd/command, чтобы посмотреть использование каждой команды, например:
$ go doc cmd/compile
Usage:
go tool compile [flags] file...
The specified files must be Go source files and all part of the same package.
...Флаги, поддерживаемые cmd/compile, — это те же флаги, которые поддерживает gcflags. Разница между go tool compile и go build в том, что первый только отвечает за компиляцию и принимает только файлы в качестве параметров, а второй может принимать папки, пакеты, файлы в качестве параметров, и не только компилирует исходный код, но и связывает файлы, очищает ненужные файлы и т.д. Первый — часть последнего. Мы можем вывести команды, выполняемые в процессе build:
$ go build -n main.go
#
# internal/goarch
#
mkdir -p $WORK\b004\
cat >$WORK\b004\importcfg << 'EOF' # internal
# import config
EOF
"/golang/pkg/tool/windows_amd64/compile.exe" -o "$WORK/b004/_pkg_.a" -trimpath "$WORK/b004=>" -p internal/goarch -std -+ -complete -buildid 3gunEkUExGdhOPa2rFsh/3gunEkUExGdhOPa2rFsh -goversion go1.21.0 -c=4 -nolocalimports -importcfg "$WORK/b004/importcfg" -pack "/golang/src/internal/goarch/goarch.go" "/golang/src/internal/goarch/goarch_amd64.go" "/golang/src/internal/goarch/zgoarch_amd64.go"
"/golang/pkg/tool/windows_amd64/buildid.exe" -w "$WORK/b004/_pkg_.a" # internal
...В процессе видно /golang/pkg/tool/windows_amd64/compile.exe — именно вызывается компилятор. Кроме compile, есть много других инструментов — многие команды go фактически являются их псевдонимами.
clean
Команда clean используется для удаления объектных файлов, созданных в процессе компиляции
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.Она поддерживает следующие флаги:
-i: удалить соответствующие архивные файлы или двоичные файлы-n: вывести команды, которые будут выполнены при очистке, но не выполнять их-x: вывести команды, которые будут выполнены при очистке, и выполнить их-r: рекурсивно очищать черезimport path-cache: удалить весь кэш, созданныйgo build-testcache: удалить весь кэш тестов-modcache: удалить весь кэш загруженных модулей-fuzzcache: удалить кэш, созданныйfuzz test
При использовании go tool compile компилятор вызывается напрямую, без множества завершающих действий, как у go build, поэтому создаются объектные файлы. Например, при выполнении команды:
go tool compile -N -S -l main.goСоздаётся файл с именем main.o. Используйте команду go clean для удаления. Или используйте параметр -n, чтобы вывести команды, которые будут выполнены:
$ go clean -n
rm -f golearn golearn.exe golearn golearn.exe golearn.test golearn.test.exe golearn.test golearn.test.exe api api.exe main main.exeОчистка кэша компиляции удалит кэш компиляции в каталоге GOCACHE:
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02Очистка кэша fuzz test — этот кэш по умолчанию хранится в каталоге GOCACHE/fuzz/:
$ go clean -fuzzcache -n
rm -rf /cache/fuzzfix
Язык Go существует уже более десяти лет на момент написания этой статьи. В процессе постоянных обновлений и изменений языка неизбежно возникают проблемы несовместимости из-за изменений API. Команда fix создана именно для этого — она обнаруживает устаревшие API в исходных файлах и заменяет их новыми.
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.Она принимает папки, имена файлов, каталоги в качестве параметров, принимает флаг -fix для указания, какие изменения вносить. Посмотреть доступные значения можно через got tool fix -help:
$ go tool fix -help
usage: go tool fix [-diff] [-r fixname,...] [-force fixname,...] [path ...]
-diff
display diffs instead of rewriting files
-force string
force these fixes to run even if the code looks updated
-go string
go language version for files
-r string
restrict the rewrites to this comma-separated list
Available rewrites are:
buildtag
Remove +build comments from modules using Go 1.18 or later
context
Change imports of golang.org/x/net/context to context
...Пример: в исходном коде используется пакет golang.org/x/net/context
package main
import (
"fmt"
"golang.org/x/net/context"
)
func main() {
background := context.Background()
fmt.Println(background.Err())
}Используйте go fix для исправления, заменив его на context из стандартной библиотеки:
$ go fix -fix context main.goТакже можно посмотреть изменения без замены:
$ go tool fix -r context -diff main.go
main.go: fixed context
diff main.go fixed/main.go
--- main.go
+++ fixed/main.go
@@ -1,8 +1,8 @@
package main
import (
+ "context"
"fmt"
- "golang.org/x/net/context"
)
func main() {За более чем десять лет существования Go доступно только девять параметров замены — видно, что совместимость поддерживается достаточно хорошо.
fmt
Команда fmt — это встроенный инструмент форматирования Go для форматирования исходных файлов Go.
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.Посмотрите подробную документацию через команду go doc gofmt:
$ go doc cmd/gofmt
Gofmt formats Go programs. It uses tabs for indentation and blanks for
alignment. Alignment assumes that an editor is using a fixed-width font.
Usage:
gofmt [flags] [path ...]
The flags are:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
-e
Print all (including spurious) errors.
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
-r rule
Apply the rewrite rule to the source before reformatting.
-s
Try to simplify code (after applying the rewrite rule, if any).
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.gofmt использует табуляцию для отступов и пробелы для выравнивания. По умолчанию отформатированный код выводится в стандартный вывод, а не перезаписывает исходный файл. Команда go fmt фактически использует команду gofmt, которая является отдельным двоичным файлом, расположенным в каталоге GOROOT/bin.
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*Добавьте флаг -n к команде go fmt, чтобы увидеть инструкцию, которая будет выполнена:
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.goВидно, что go fmt — это псевдоним для gofmt -l -w. Команда gofmt имеет следующие параметры:
-d: вывести различия до и после форматирования-e: вывести все ошибки-l: вывести имена изменённых файлов-r: применить правило форматирования-s: попытаться упростить код-w: перезаписать исходный файл, при ошибке восстановить резервную копию
Предположим, есть следующий исходный файл:
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")}Через параметр -d можно просмотреть изменения:
$ gofmt -d main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
-fmt.Println("hello world!")}
-
+ fmt.Println("hello world!")
+}Параметр -l выведет имя файла, который будет изменён:
$ gofmt -l .
main.goЕсли есть синтаксические ошибки, параметр -e выведет более подробную информацию:
$ gofmt -d -e main.go
main.go:6:27: missing ',' in argument list
...Параметр -w применит изменения к исходному файлу:
$ gofmt -l -w .
main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}Вы можете заметить, что как инструмент форматирования gofmt вообще не предоставляет никаких пользовательских настроек. Это отражает отношение официального Go: не нужно персонализировать, стиль кода всех лучше сделать единообразным. Однако есть один пользовательский параметр — правила замены форматирования кода, которые можно настроить. Формат:
pattern -> replacementНапример, удаление избыточных скобок:
(a) -> aПросмотр изменений файла:
$ gofmt -r "(a) -> a" -d -l .
main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
- fmt.Println(("hello world!"))
+ fmt.Println("hello world!")
}Видно, что gofmt удалит избыточные скобки.
get
Команда get — определённо одна из самых часто используемых при разработке на Go. Её роль — загрузить исходный код пакета по указанному адресу в каталог, соответствующий GOMODCACHE.
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.-u: попытаться обновить минорную версию и версию патча пакета. Если основная версия изменяется, напримерv1->v2, обновление не произойдёт.-t: обновить версию зависимостей в тестах-v: выводить компилируемые пакеты, фактически является одним из параметровbuild flags
В ранние времена команда go get работала аналогично go install — она загружала и компилировала пакеты. Однако с появлением и совершенствованием Go модулей эта функция была упразднена. Теперь команда get чаще всего используется для загрузки модулей Go и разрешения зависимостей.
install
Команда install аналогична команде get — обе используются для загрузки сторонних зависимостей. Разница в том, что get загружает исходный код, а install компилирует исходный код в исполняемый двоичный файл для текущей системы. Двоичные файлы сохраняются в каталоге GOBIN, или GOPATH/bin. Основная функция этой команды — загрузка публичных сторонних инструментов командной строки.
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.Команда install принимает флаги сборки и имена пакетов в качестве параметров. При включённом gomod имя пакета должно содержать номер версии. Например, загрузка отладчика delve:
$ go install -x github.com/go-delve/delve/cmd/dlv@latestlist
Команда list выводит список пакетов в указанном месте, по одному на строку, и поддерживает настраиваемый формат вывода. Использование требует нахождения в проекте с поддержкой gomod.
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.Поддерживаемые параметры:
-f: параметр форматирования-json: вывод в формате JSON-compiled: показать все пакеты, которые будут скомпилированы компилятором-deps: показать каждый пакет и имя каждого пакета, от которого он зависит-test: показать тестовый пакет для каждого пакета-e: нормально выводить при ошибках в пакетах-find: не разрешать зависимости этих пакетов-export: при использовании этого параметра установить значение поляPackage.Exportравным файлу с последней информацией об экспорте содержащем указанный пакет
Параметры информации о модуле:
-m: выводить модули вместо пакетов-versions: показать всю доступную информацию о модуле-retracted: показать отозванные версии модуля
Параметр [packages] может быть именем пакета, папкой, или all (означает везде). При использовании параметра -m, all означает все зависимости, на которые ссылается текущий модуль.
mod
go mod — команда, специально предназначенная для управления модулями Go.
$ go mod help
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod <command>" for more information about a command.Подкоманды:
download: загрузить все зависимости, указанные в файлеgo.mod, в локальный кэшedit: редактировать файлgo.mod, предоставляет интерфейс командной строки для других инструментов или скриптовinit: инициализировать проект gomod в текущем каталогеtidy: загрузить недостающие зависимости, удалить неиспользуемые зависимостиgraph: вывести граф зависимостейverify: проверить локальные зависимостиwhy: объяснить, почему эти модули являются зависимостямиvendor: экспортировать зависимости проекта в каталог vendor
work
Команда work — это инструмент локальной разработки для управления несколькими модулями Go.
$ go work help
Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
The commands are:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
vendor make vendored copy of dependencies
Use "go help work <command>" for more information about a command.vet
Команда vet — это инструмент статического анализа ошибок исходного кода Go, аналогичный инструментам lint в других языках, например Eslint.
$ go vet -h
usage: go vet [build flags] [-vettool prog] [vet flags] [packages]
Run 'go help vet' for details.
Run 'go tool vet help' for a full list of flags and analyzers.
Run 'go tool vet -help' for an overview.Сначала рассмотрим простой пример:
$ cat main.go
package main
import "fmt"
func main(){
fmt.Println("hello world!"
}Выполним go vet без параметров в том же каталоге:
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)vet сообщит, в каком файле и на какой строке возникла проблема.
test
$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' and 'go help testflag' for details.Команда test — это команда в инструментарии Go, предоставляющая функциональность тестирования. Эта функция очень важна — для программного обеспечения полное тестирование незаменимо. Здесь только кратко описывается использование команды test.
Директивы
В отличие от команд, директивы Go существуют в исходных файлах в жёстко запрограммированном виде. У них есть более техническое название: директивы компиляции (pragma directives).
Компилятор и компоновщик изменяют своё поведение под их влиянием, достигая контроля над компиляцией. Это отчасти похоже на макросы в языке C. Конечно, не все директивы используются для влияния на компиляцию — некоторые используются для других функциональных действий, например, директива generate обычно используется для генерации кода. Эти директивы обычно существуют в виде комментариев с префиксом //go:, без пробелов внутри, например, директива //go:generate.
Все типы директив делятся на два вида:
- Функциональные директивы — это функциональные директивы, предоставляемые Go, можно использовать свободно, например,
generate,embed,build - Директивы компилятора — эти директивы следует использовать с осторожностью, необдуманное использование может привести к непредсказуемым результатам
generate
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]Директива generate — как следует из названия, связана с генерацией. Обычно её роль — выполнять команды, которые генерируют код и обновляют исходный код, хотя фактически она может выполнять любые команды. Кроме того, директива generate, в отличие от других директив, имеет специальную команду для выполнения всех директив generate в исходных файлах.
embed
Директива embed была добавлена в версии 1.16. Её роль — упаковать статические файлы вместе с двоичным файлом, например, HTML-шаблоны. Формат:
//go:embed patternpattern может быть выражением glob, папкой или конкретным файлом.
build
Директива //go:build была представлена в версии 1.17 для замены предыдущей директивы // +build. Она поддерживает логические выражения и имеет более строгий синтаксис.
line
Директива line влияет на номер строки, номер столбца и имя файла следующей строки. Её роль ограничена этим, в основном может использоваться для отладки ошибок.
linkname
Эта директива может использоваться для связывания функций или глобальных переменных других пакетов, даже если они приватные. Эта операция часто встречается в стандартной библиотеке, особенно в runtime.
noinline
Директива noinline указывает, что функция запрещена для оптимизации инлайнинга, даже если она очень простая.
nospilit
Директива nospilit используется для пропуска проверки переполнения стека.
noescape
Директива noescape указывает, что текущая функция не вызывает поведения, связанного с escape-анализом памяти.
uintptrescapes
Директива uintptrescapes указывает, что параметры типа uintptr в функции были преобразованы в значения указателя и escape в кучу.
norace
Директива norace указывает, что доступ к памяти функции больше не требует анализа гонок данных.
TIP
Некоторые директивы ограничены для использования только пакетом runtime и недоступны извне. Они затрагивают более глубокие вещи. Чтобы узнать больше, см. Runtime-only compiler directives.
