Skip to content

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

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

text
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 после указанной команды, например

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

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

sh
$ 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

sh
$ 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 выводит комментарии документации для указанного пакета, константы, функции, типа, переменной, метода и даже полей структуры. Без параметров она выводит комментарии текущего пакета

sh
$ go doc

Также можно указать конкретный пакет, например, посмотреть комментарии документации пакета runtime

sh
$ 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.
......

Или определённый тип

sh
$ 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.
      ...

Или определённую функцию

sh
$ 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, которая не экспортируется

sh
$ go doc -u runtime.inf
package runtime // import "runtime"

var inf = float64frombits(0x7FF0000000000000)

Используйте команду doc разумно, чтобы вам было удобнее читать документацию.

Другой способ читать документацию команд — читать исходный код, потому что документация некоторых команд может быть не такой подробной, а в исходном коде могут быть более детальные пояснения. Поскольку все эти команды написаны на Go, их удобно читать. Все команды находятся в пакете src/cmd, каждый подпакет — это отдельная команда, точка входа находится в файле cmd/go/main.go

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

sh
$ 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
$ go version -h
usage: go version [-m] [-v] [file ...]

При выполнении без параметров она выводит текущую версию языка Go

sh
$ go version
go version go1.21.0 windows/amd64

Она также принимает путь к файлу в качестве параметра и выводит версию Go, использованную при компиляции всех распознаваемых двоичных файлов по этому пути.

sh
$ 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 выводит информацию о модулях двоичного файла, а также некоторые параметры компиляции. Ниже приведён простой пример.

sh
$ 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.

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

При выполнении без параметров команда выводит значения всех переменных среды Go

sh
$ go env
set GO111MODULE=on
set GOARCH=amd64
...

Указав имя переменной среды в качестве параметра, можно вывести значение только этой переменной

sh
$ go env GO111MODULE
on

Добавьте -json, чтобы вывести в формате JSON

sh
$ go env -json
{
        "AR": "ar",
        "CC": "gcc",
    ......
}

С помощью флага -w и параметра в формате var=value можно навсегда изменить значение переменной

sh
$ go env -w GO111MODULE=on

Используя флаг -u, можно вернуть переменную к значению по умолчанию

sh
$ go env -u GO111MODULE

Выполните go help environment, чтобы увидеть описание каждой переменной среды

sh
$ 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 и время сборки.

sh
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35Z

Значение переменной runtime.Version совпадает со значением GOVERSION, и эта переменная среды не может быть изменена.

GOENV

В каталоге $GOROOT есть конфигурационный файл по умолчанию с именем go.env

sh
$ 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, то есть операционная система данного компьютера. Доступные значения:

  • linux
  • darwin
  • windows
  • netbsd
  • aix
  • android

Фактически поддерживаемых операционных систем больше. Используйте команду go tool dist list, чтобы посмотреть все поддерживаемые значения

sh
$ 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
windows

GOARCH

При компиляции значение GOARCH определяет, какой набор инструкций архитектуры CPU будет использоваться при компиляции. Значение по умолчанию — GOHOSTARCH, то есть архитектура CPU данного компьютера. Доступные значения:

  • amd64
  • 386
  • arm
  • ppc64

Фактически поддерживаемых архитектур больше. Используйте команду go tool dist list, чтобы посмотреть все поддерживаемые значения

sh
$ 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 не может быть изменено напрямую и может быть переопределено только переменной среды операционной системы.

sh
$ 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/tool
  • bin — хранит двоичные файлы. По умолчанию там только два исполняемых файла: go и gofmt. Каталог $GOROOT/bin должен быть добавлен в системные переменные, иначе вы не сможете использовать команду go.
  • src — хранит исходный код Go
  • VERSION — этот файл содержит информацию о версии языка Go
  • go.env — этот файл является конфигурационным файлом env по умолчанию

GOPATH

Значение GOPATH по умолчанию — $HOME/go. Эта переменная среды указывает, где искать импортируемые файлы при разборе операторов import. В ранние времена, когда не было gomod, GOPATH использовался специально для хранения различных сторонних библиотек. Его структура выглядела так:

sh
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, иначе это не будет иметь никакого эффекта.

sh
$ 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.

sh
$ 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.mod
  • on — использовать 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 можно посмотреть команды, выполняемые в процессе загрузки зависимостей, и узнать, используется ли прокси.

sh
$ 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/myorganization

GONOPROXY

Указывает, какие зависимости не должны использовать прокси. Правила такие же, как у 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=*:off

GOWORK

Устанавливает, включено ли рабочее пространство. По умолчанию пусто — включено. Если установить 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.

sh
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.

Она принимает три параметра: путь вывода файла, указанный флагом -o, флаги сборки build flags для определения поведения компиляции, и пакет для компиляции — этот параметр должен быть последним. Ниже приведён простой пример без использования флагов сборки.

sh
# Windows
$ go build -o .\bin\golearn.exe golearn

# macOS / Linux
$ go build -o ./bin/golearn golearn

./bin/golearn.exe — это путь вывода, golearn — модуль для компиляции. Также может быть входным файлом или папкой. Например, следующий простой пример использует main.go в качестве входного файла для компиляции.

sh
# 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", чтобы увидеть возможные значения, например:

sh
$ 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. Используйте следующую команду, чтобы просмотреть доступные значения параметров:

sh
$ 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. Также нужно отключить оптимизацию и инлайнинг, чтобы восстановить исходную форму:

sh
$ 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 — их около двух-трёх десятков.

sh
$ 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 — очень полезная функция. Он позволяет определить значение строковой переменной указанного пакета во время компоновки. С помощью этой функции можно удобно внедрять метаданные во время компиляции. И это просто переменная, поэтому её легко получить во время выполнения. Вот простой пример:

go
package main

import "fmt"

var (
  Version string
)

func main() {
  fmt.Println(Version)
}

Выполните команду:

sh
go build -ldflags "-X main.Version=$(git describe --always)" main.go

После запуска будет выведена контрольная сумма SHA1 коммита git:

5e3fd7a

Другие полезные параметры:

  • -w: не генерировать DWARF — информацию для отладки исходного кода
  • -s: отключить таблицу символов

Эти два параметра часто используются вместе и могут значительно уменьшить размер скомпилированного двоичного файла — примерно на 40-50%. Недостаток очевиден — невозможность отладки. Пример:

sh
$ go build -ldflags="-w -s" main.go

Кросс-компиляция

Компиляция Go имеет два основных преимущества: первое — скорость, второе — кросс-компиляция. Кросс-компиляция означает возможность компиляции в целевой код для других систем локально, например, на windows можно скомпилировать двоичные файлы для linux или darwin, и наоборот. Кросс-компиляция поддерживается многими языками, это не новинка, но кросс-компиляция Go очень проста — достаточно выполнить два шага:

  1. Установить переменную среды GOOS, выбрать целевую операционную систему
  2. Установить переменную среды GOARCH, выбрать целевую архитектуру CPU
  3. Компилировать с помощью go build как обычно

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

makefile
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:

go
// +build product

package main

import "fmt"

func main() {
  fmt.Println("product")
}

Файл debug.go:

go
// +build debug

package main

import "fmt"

func main() {
  fmt.Println("debug")
}

Оба имеют директиву // +build, указывающую, при каких условиях они будут скомпилированы. Основной формат:

go
// +build tag1 tag2

package pkg_name

Есть несколько обязательных правил:

  1. Между // и +build должен быть пробел
  2. Она должна находиться над объявлением пакета
  3. Между ней и объявлением пакета должна быть пустая строка

Кроме того, с помощью простых разделителей можно реализовать логическое управление: пробел означает OR, запятая означает AND, ! означает NOT. Пример:

go
// +build windows linux

package pkg_name

Означает, что на платформе windows или linux текущий файл будет скомпилирован.

go
// +build windows,amd64,!cgo linux,i386,cgo

package pkg_name

Этот пример означает, что файл будет скомпилирован только на платформе windows с архитектурой amd64 и без cgo, или на платформе linux с архитектурой i386 и с cgo. Если вы просто не хотите, чтобы файл участвовал в компиляции, используйте ignore:

go
// +build ignore

package pkg_name

Также могут быть многострочные директивы:

go
// +build windows
// +build amd64

package pkg_name

Многострочные директивы обрабатываются как AND. Для тегов платформы и архитектуры go автоматически передаёт их при компиляции. Мы также можем передавать пользовательские теги. Возьмём два файла из начала:

sh
$ 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.

sh
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.

Она также поддерживает флаги сборки команды build, а также предоставляет параметр -exec для указания, какая программа будет запускать двоичный файл. [arguments...] — это аргументы запуска программы. Пример:

go
package main

import (
  "fmt"
  "os"
)

var (
  Version string
)

func main() {
  fmt.Println(Version)
  fmt.Println(os.Args[1:])
}

Используйте go run для запуска:

sh
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]

В целом использование аналогично go build, поэтому подробно не описывается.

tool

Команда tool сама по себе не имеет функций, её роль — напрямую вызывать инструменты в каталоге cmd/. Например, cmd/compile — встроенный компилятор. Через go tool можно напрямую вызывать эти инструменты без необходимости вручную запускать их двоичные файлы.

sh
$ go tool -h
usage: go tool [-n] command [args...]

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

sh
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vet

Эти инструменты хранятся в каталоге GOROOT/pkg/tool, сгруппированы по операционной системе и архитектуре CPU:

sh
$ ls $GOROOT/pkg/tool/windows_amd64/ -1
addr2line.exe*
asm.exe*
buildid.exe*
cgo.exe*
compile.exe*
...

Используйте формат go doc cmd/command, чтобы посмотреть использование каждой команды, например:

sh
$ 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:

sh
$ 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 используется для удаления объектных файлов, созданных в процессе компиляции

sh
$ 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, поэтому создаются объектные файлы. Например, при выполнении команды:

sh
go tool compile -N -S -l main.go

Создаётся файл с именем main.o. Используйте команду go clean для удаления. Или используйте параметр -n, чтобы вывести команды, которые будут выполнены:

sh
$ 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:

sh
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02

Очистка кэша fuzz test — этот кэш по умолчанию хранится в каталоге GOCACHE/fuzz/:

sh
$ go clean -fuzzcache -n
rm -rf /cache/fuzz

fix

Язык Go существует уже более десяти лет на момент написания этой статьи. В процессе постоянных обновлений и изменений языка неизбежно возникают проблемы несовместимости из-за изменений API. Команда fix создана именно для этого — она обнаруживает устаревшие API в исходных файлах и заменяет их новыми.

sh
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.

Она принимает папки, имена файлов, каталоги в качестве параметров, принимает флаг -fix для указания, какие изменения вносить. Посмотреть доступные значения можно через got tool fix -help:

sh
$ 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

sh
package main

import (
  "fmt"
  "golang.org/x/net/context"
)

func main() {
  background := context.Background()
  fmt.Println(background.Err())
}

Используйте go fix для исправления, заменив его на context из стандартной библиотеки:

sh
$ go fix -fix context main.go

Также можно посмотреть изменения без замены:

sh
$ 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.

sh
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.

Посмотрите подробную документацию через команду go doc gofmt:

sh
$ 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.

sh
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*

Добавьте флаг -n к команде go fmt, чтобы увидеть инструкцию, которая будет выполнена:

sh
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.go

Видно, что go fmt — это псевдоним для gofmt -l -w. Команда gofmt имеет следующие параметры:

  • -d: вывести различия до и после форматирования
  • -e: вывести все ошибки
  • -l: вывести имена изменённых файлов
  • -r: применить правило форматирования
  • -s: попытаться упростить код
  • -w: перезаписать исходный файл, при ошибке восстановить резервную копию

Предположим, есть следующий исходный файл:

go
$ cat main.go
package main

import "fmt"

func main() {
fmt.Println("hello world!")}

Через параметр -d можно просмотреть изменения:

sh
$ 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 выведет более подробную информацию:

sh
$ gofmt -d -e main.go
main.go:6:27: missing ',' in argument list
...

Параметр -w применит изменения к исходному файлу:

sh
$ gofmt -l -w .
main.go

$ cat main.go
package main

import "fmt"

func main() {
        fmt.Println("hello world!")
}

Вы можете заметить, что как инструмент форматирования gofmt вообще не предоставляет никаких пользовательских настроек. Это отражает отношение официального Go: не нужно персонализировать, стиль кода всех лучше сделать единообразным. Однако есть один пользовательский параметр — правила замены форматирования кода, которые можно настроить. Формат:

pattern -> replacement

Например, удаление избыточных скобок:

(a) -> a

Просмотр изменений файла:

sh
$ 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.

sh
$ 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. Основная функция этой команды — загрузка публичных сторонних инструментов командной строки.

sh
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.

Команда install принимает флаги сборки и имена пакетов в качестве параметров. При включённом gomod имя пакета должно содержать номер версии. Например, загрузка отладчика delve:

sh
$ go install -x github.com/go-delve/delve/cmd/dlv@latest

list

Команда list выводит список пакетов в указанном месте, по одному на строку, и поддерживает настраиваемый формат вывода. Использование требует нахождения в проекте с поддержкой gomod.

sh
$ 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.

sh
$ 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.

bash
$ 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.

sh
$ 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.

Сначала рассмотрим простой пример:

sh
$ cat main.go
package main

import "fmt"

func main(){
        fmt.Println("hello world!"
}

Выполним go vet без параметров в том же каталоге:

sh
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)

vet сообщит, в каком файле и на какой строке возникла проблема.

test

sh
$ 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

sh
$ 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
//go:embed pattern

pattern может быть выражением 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.

Golang by www.golangdev.cn edit