[Перевод] Обзор команды Go

задняя часть Go Программа перевода самородков

Меня иногда спрашивают:«Почему вам нравится использовать Go?»Я часто упоминаю об этомgoИнструментальные команды, которые являются частью языка. Есть некоторые команды - напримерgo fmtиgo build-- Я использую его каждый день, и некоторые команды -- напримерgo tool pprof- Я использую их для решения конкретных задач. Но в любом случае я ценю то, что команда go упрощает управление моим проектом и его обслуживание.

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

Если вы давно используете Go, эта статья может быть не для вас, но, надеюсь, вы найдете здесь команды и параметры, о которых раньше не знали 😀

Информация в этой статье была написана для Go 1.12 и предполагает, что вы разрабатываетеmodule-enabledс проект.

  1. установить команду
  2. Просмотр информации об окружающей среде
  3. развивать
  4. контрольная работа
  5. предварительная проверка
  6. Сборка и развертывание
  7. Диагностика проблем и оптимизация
  8. Управление зависимостями
  9. обновить до новой версии
  10. сообщить о проблеме
  11. Шпаргалка

установить команду

В этой статье я в основном сосредоточусь на части команды go. Но здесь также будут некоторые упоминания, которые не являются частью стандартного выпуска Go 12.2.

Когда вы устанавливаете команды в Go 12.2, вам сначала нужно убедиться, что вы в данный момент находитесь в каталоге с поддержкой модулей.за пределами(я обычно перехожу к/tmpПод содержанием). После этого вы можете использоватьGO111MODULE=on go getкоманда для установки. Например:

$ cd /tmp
$ GO111MODULE=on go get golang.org/x/tools/cmd/stress

Эта команда загрузит соответствующие пакеты и зависимости, создаст исполняемый файл и добавит его в вашу установку.GOBINПод содержанием. Если вы явно не установитеGOBINкаталог, исполняемый файл будет добавлен вGOPATH/binПод содержанием. Но в любом случае вы должны убедиться, что у вас есть соответствующий каталог на вашем системном пути.

Примечание. Этот процесс немного неуклюж и, надеюсь, будет улучшен в будущих версиях Go. ты сможешьIssue 30515Следите за обсуждением этого вопроса.

Просмотр информации об окружающей среде

ты можешь использоватьgo envКоманда отображает текущую рабочую среду Go. Это может быть полезно, если вы работаете на незнакомом компьютере.

$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/alex/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/alex/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build245740092=/tmp/go-build -gno-record-gcc-switches"

Если вас интересуют какие-то конкретные значения, вы можете передать эти значения в качестве параметров вgo env. Например:

$ go env GOPATH GOOS GOARCH
/home/alex/go
linux
amd64

для отображенияgo envСодержимое всех переменных и значений команды можно запустить:

$ go help environment

развивать

запустить код

При разработке используйтеgo runКод выполнения команды очень удобен. По сути, это ярлык для компиляции кода, в/tmpСоздайте исполняемый двоичный файл в каталоге и запустите его за один шаг.

$ go run .          # 运行当前目录下的包
$ go run ./cmd/foo  # 运行 ./cmd/foo 目录下的包

Примечание. Начиная с версии Go 1.11, при выполненииgo runкоманда, вы можетепуть входящего пакета, как мы упоминали выше. Это означает, что больше нет необходимости использовать что-то вродеgo run *.goЭто включает в себя обходной путь для расширения с подстановочными знаками, которое запускает несколько файлов. Мне очень нравится это улучшение.

получить зависимости

если у вас естьмодуль включен, что когда вы бежитеgo run,go testилиgo buildАналогичные команды, все внешние зависимости будут загружены автоматически (или рекурсивно) для достиженияimportутверждение. По умолчанию будет загружен последний тег зависимости, если тег недоступен, будет использоваться последняя зафиксированная зависимость.

Если вы заранее знаете, что вам нужна конкретная версия зависимости (отличная от той, которую Go получает по умолчанию), вы можете использоватьgo getТакже укажите соответствующий номер версии или хэш коммита. Например:

$ go get github.com/foo/bar@v1.2.3
$ go get github.com/foo/bar@8e1b8d3

Если полученная зависимость содержитgo.modфайл, затемего зависимостине будет указан втвой go.modв файле. И наоборот, если загружаемые вами зависимости не содержатgo.modфайл, затем его зависимостибудетВ твоемgo.modфайл и будет сопровождаться//indirectПримечания.

это означает, что вашgo.modфайл не обязательно показывает все зависимости вашего проекта в одном месте, но вы можете использоватьgo listИнструменты просматривают их следующим образом:

$ go list -m all

Иногда вы можете задаться вопросом, почему это зависимость? **ты можешь использоватьgo mod whyКоманда отвечает на этот вопрос. Эта команда покажет кратчайший путь от пакета основного модуля до заданной зависимости. Например:

$ go mod why -m golang.org/x/sys
# golang.org/x/sys
github.com/alexedwards/argon2id
golang.org/x/crypto/argon2
golang.org/x/sys/cpu

Уведомление:go mod whyКоманда вернет ответы для большинства (но не для всех зависимостей). ты сможешьIssue 27900отследить эту проблему.

Если вы заинтересованы в анализе или визуализации зависимостей вашего приложения, вы также можете проверитьgo mod graphинструмент. существуетздесьСуществует отличный учебник и пример кода для создания визуальных зависимостей.

Наконец, загруженные зависимости сохраняются по адресуGOPATH/pkg/modизкеш модулясередина. Если вам нужно очистить кеш модуля, вы можете использоватьgo cleanинструмент. Но будьте осторожны: это удалитВсе элементызагруженных зависимостей.

$ go clean -modcache

перестроить код

вы можете быть знакомы с использованиемgofmtинструмент. Он может автоматически форматировать код, но также поддерживает переход кпереписать правила. Вы можете использовать его для рефакторинга кода. Я продемонстрирую это ниже.

Предположим, у вас есть следующий код, вы хотитеfooИзмените переменную наFooчтобы экспортировать его.

var foo int

func bar() {
    foo = 1
	fmt.Println("foo")
}

Для этого вы можете использоватьgofmtиз-rПараметр реализует правило перезаписи,-dпараметры показывают разницу изменений,-wреализация параметрана местеИзмените это следующим образом:

$ gofmt -d -w -r 'foo -> Foo' .
-var foo int
+var Foo int

 func bar() {
-	foo = 1
+	Foo = 1
 	fmt.Println("foo")
 }

Заметили, насколько это умнее простого поиска и замены?fooпеременная была изменена, ноfmt.Println()в предложении"foo"Струны не заменяются. Также обратите внимание, чтоgofmtКоманды работают рекурсивно, поэтому приведенная выше команда выполнит все команды в текущем каталоге и подкаталогах.*.goвыполнить в файле.

Если вы хотите использовать эту функцию, я предлагаю вам сначала не приносить-wПараметр запускает правила перезаписи и сначала проверяет различия, чтобы убедиться, что код изменяется так, как вы хотите.

Давайте рассмотрим немного более сложный пример. Предположим, вы хотите обновить свой код, чтобы использовать новую версию Go 1.12.strings.ReplaceAll()метод заменяет предыдущийstrings.Replace()метод. Чтобы внести это изменение, вы можете запустить:

$ gofmt -w -r 'strings.Replace(a, b, c, -1) -> strings.ReplaceAll(a, b, c)' .

В правилах перезаписи один символ нижнего регистра используется в качестве подстановочного знака для соответствия любому выражению, и эти совпадающие выражения будут заменены.

Ознакомьтесь с документацией Go

ты можешь использоватьgo docинструмент для просмотра документации стандартной библиотеки в терминале. Я часто использую его во время разработки, чтобы быстро что-то найти — например, название или сигнатуру конкретной функции. Я думаю, это лучше, чем просматриватьвеб-документацияЭто быстрее и доступно в автономном режиме.

$ go doc strings            # 查看 string 包的简略版文档 
$ go doc -all strings       # 查看 string 包的完整版文档 
$ go doc strings.Replace    # 查看 strings.Replace 函数的文档
$ go doc sql.DB             # 查看 database/sql.DB 类型的文档 
$ go doc sql.DB.Query       # 查看 database/sql.DB.Query 方法的文档

вы также можете использовать-srcпараметры для отображения соответствующего исходного кода Go. Например:

$ go doc -src strings.Replace   # 查看 strings.Replace 函数的源码

контрольная работа

запустить тест

ты можешь использоватьgo testИнструмент тестирует код в проекте следующим образом:

$ go test .          # 运行当前目录下的全部测试
$ go test ./...      # 运行当前目录和子目录下的全部测试
$ go test ./foo/bar  # 运行 ./foo/bar 目录下的全部测试

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

$ go test -race ./...

Здесь важно отметить, что включение обнаружения гонки увеличит общее время выполнения теста. Поэтому, если вы часто запускаете тесты в рабочем процессе TDD (разработка через тестирование), вы можете использовать этот метод для выполнения тестов перед фиксацией.

Начиная с версии 1.10, Go находится на уровне пакетов.Результаты проверки кеша. Если пакет не изменился во время тестового прогона и вы используете тот же кэшируемыйgo testинструмента, то будут отображаться кэшированные результаты теста и"(cached)"отметил Марк. Это полезно для ускорения тестовых прогонов больших кодовых баз. Если вы хотите, чтобы тест выполнялся полностью (и избегал кэширования), вы можете использовать-count=1параметры или использоватьgo cleanИнструмент очищает все кэшированные результаты тестов.

$ go test -count=1 ./...    # 运行测试时绕过测试缓存
$ go clean -testcache       # 删除所有的测试结果缓存

Примечание. Кэшированные результаты теста хранятся вGOCACHEв каталоге. если вы не увереныGOCACHEРасположение каталога на машине, пожалуйста, введитеgo env GOCACHEПроверять.

ты можешь использовать-runпараметр будетgo testОграничено выполнением только определенных тестов (и подтестов).-runПараметр принимает регулярное выражение, и выполняются только тесты с именами, соответствующими регулярному выражению. мне нравится использовать его с-vПараметры объединены для включения подробного режима, в котором отображаются имена запущенных тестов и подтестов. Это был полезный способ убедиться, что я не испортил регулярное выражение, и убедиться, что тесты, которые я ожидал, выполняются!

$ go test -v -run=^TestFooBar$ .          # 运行名字为 TestFooBar 的测试
$ go test -v -run=^TestFoo .              # 运行那些名字以 TestFoo 开头的测试
$ go test -v -run=^TestFooBar$/^Baz$ .    # 只运行 TestFooBar 的名为 Baz 的子测试

Стоит отметить два параметра-short(можно использовать дляпропускать длительные тесты-failfast(прекратите выполнение дальнейших тестов после первого сбоя). Пожалуйста, обрати внимание,-failfastПредотвратит кеширование результатов теста.

$ go test -short ./...      # 跳过长时间运行的测试
$ go test -failfast ./...   # 第一次失败后停止运行进一步的测试

Анализ покрытия тестами

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

$ go test -cover ./...
ok  	github.com/alexedwards/argon2id	0.467s	coverage: 78.6% of statements

Вы также можете сделать это, используя-coverprofileпараметры для создания обзора покрытия и использованияgo tool cover -htmlКоманда просматривается в браузере. нравится:

$ go test -coverprofile=/tmp/profile.out ./...
$ go tool cover -html=/tmp/profile.out

Это даст вам список всех тестовых файлов с возможностью навигации, где код, выделенный зеленым цветом, покрыт тестами, а код, выделенный красным, не покрыт тестами.

Вы можете пойти дальше, если хотите. настраивать-covermode=countпараметр, чтобы профиль покрытия записывал точное выполнение каждого оператора во время тестачастота.

$ go test -covermode=count -coverprofile=/tmp/profile.out ./...
$ go tool cover -html=/tmp/profile.out

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

Примечание: если вы используетеt.Parallel()команду, вы должны использовать-covermode=atomicзаменять-covermode=countдля обеспечения точного подсчета.

Наконец, если у вас нет веб-браузера для просмотра профилей покрытия, вы можете просмотреть разбивку покрытия тестами по функциям/методам в терминале с помощью следующей команды:

$ go tool cover -func=/tmp/profile.out
github.com/alexedwards/argon2id/argon2id.go:77:		CreateHash		87.5%
github.com/alexedwards/argon2id/argon2id.go:96:		ComparePasswordAndHash	85.7%
...

испытание давлением

ты можешь использоватьgo test -countКоманда для запуска теста несколько раз подряд. Это может быть полезно, если вы хотите проверить наличие спорадических или периодических сбоев. Например:

$ go test -run=^TestFooBar$ -count=500 .

В этом примереTestFooBarТест будет повторяться 500 раз подряд. Но на одну вещь вы должны обратить особое внимание, тест будет сериализованповторениеВыполнить - даже если он содержитt.Parallel()Заказ. Поэтому, если ваши тесты выполняют относительно медленные действия, такие как чтение и запись в базу данных, диск или частое взаимодействие с Интернетом, выполнение большого количества тестов может занять значительное время.

В этом случае вы можете использоватьstressИнструмент выполняет один и тот же тест несколько раз параллельно. Вы можете установить его следующим образом:

$ cd /tmp
$ GO111MODULE=on go get golang.org/x/tools/cmd/stress

нужно использоватьstressинструмент, который сначала нужно скомпилировать для конкретного тестируемого пакетатестовый двоичный файлдокумент. ты можешь использоватьgo test -cЗаказ. Например, чтобы создать тестовые двоичные файлы для пакетов в текущем каталоге:

$ go test -c -o=/tmp/foo.test .

В этом примере тестовый двоичный файл будет выводиться на/tmp/foo.test. После этого вы можете использоватьstressИнструмент выполняет определенные тесты в этом файле следующим образом:

$ stress -p=4 /tmp/foo.test -test.run=^TestFooBar$
60 runs so far, 0 failures
120 runs so far, 0 failures
...

Примечание. В приведенном выше примере я использую-pпараметры для ограниченияstressКоличество используемых параллельных процессов равно 4. Без этого параметра инструмент по умолчанию будет использовать иruntime.NumCPU()Выполнение метода приводит к тому же количеству процессов (количество процессов с количеством ядер ЦП в текущей системе).

Протестируйте все зависимости

Прежде чем создавать исполняемый файл для выпуска или развертывания или публиковать свой код, вы можете запуститьgo test allЗаказ:

$ go test all

Это запустит тесты для всех пакетов и зависимостей в модуле, включаятестовые зависимостии необходимоСтандартный пакет библиотекитесты — это может помочь проверить, что точные версии используемых зависимостей совместимы друг с другом. Выполнение может занять некоторое время, но результаты тестов хорошо кэшируются, поэтому любые будущие последующие тесты будут выполняться быстрее. Если вы хотите, вы также можете использоватьgo test -short allПропустите любые длительные тесты.

предварительная проверка

код формата

Go предоставляет два инструментаgofmtиgo fmtдля автоматического форматирования кода в соответствии с соглашениями Go. Их использование помогает поддерживать согласованность кода в файлах и проектах, а их использование перед фиксацией кода помогает уменьшить отвлекающие факторы при проверке различий между версиями файлов.

Мне нравится использовать со следующими параметрамиgofmtинструмент:

$ gofmt -w -s -d foo.go  # 格式化 foo.go 文件
$ gofmt -w -s -d .       # 递归格式化当前目录和子目录中的所有文件

Среди этих команд-wПараметр указывает инструменту перезаписать файл,-sинструмент индикации параметров, насколько это возможноупрощатькод,-dПараметр указывает на разницу в изменениях выходных данных инструмента (потому что я хотел бы знать, что изменилось). Если вы просто хотите показать имя измененного файла вместо diff, вы можете заменить его на-lпараметр.

Уведомление:gofmtКоманды работают рекурсивно. Если вы передадите что-то вроде.или./cmd/fooкаталог, он отформатирует все.goдокумент.

Еще один инструмент форматированияgo fmtэто оболочка, которая вызывает указанный файл или каталогgofmt -l -w. Вы можете использовать его следующим образом:

$ go fmt ./...

выполнить статический анализ

go vetинструменты, которые выполняют статический анализ вашего кода ивозможныйЧто-то неправильное в коде, но не указанное компилятором (синтаксически правильное), вызывает предупреждение. Такие проблемы, как недоступный код, ненужные выделения и неправильные теги сборки. Вы можете использовать его следующим образом:

$ go vet foo.go     # 对 foo.go 文件进行静态分析 
$ go vet .          # 对当前目录下的所有文件进行静态分析
$ go vet ./...      # 对当前目录以及子目录下的所有文件进行静态分析
$ go vet ./foo/bar  # 对 ./foo/bar 目录下的所有文件进行静态分析

go vetмного работает за кулисамиразные анализаторы, вы можете отключить определенные анализаторы в каждом конкретном случае. Например, чтобы отключитьcompositeАнализатор можно использовать:

$ go vet -composites=false ./...

существуетgolang.org/x/toolsЕсть несколько экспериментальных анализаторов, которые вы можете попробовать:

  • nilness: Проверка на наличие избыточных или невозможных сравнений с нулями
  • shadow: проверьте возможное непреднамеренное затенение переменных

Если вы хотите использовать их, вам нужно установить и запустить их отдельно. Например, если вы установитеnilness, вам нужно запустить:

$ cd /tmp
$ GO111MODULE=on go get golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness

После этого вы можете использовать так:

$ go vet -vettool=$(which nilness) ./...

Примечание. Начиная с Go 1.10,go testИнструмент запускается автоматически перед запуском любых тестовgo vetНебольшой набор проверок с высокой степенью достоверности. Вы можете отключить это поведение при выполнении тестов следующим образом:

$ go test -vet=off ./...

Линтинг-код

ты можешь использоватьgolintидентификационный код инструмента внеправильный стиль. иgo vetотличается, это то же самое, что и кодправильностьНе связано, но может помочь вам объединить ваш код сEffective Goи идтиCodeReviewCommentsСоглашения о стиле в align.

Он не входит в стандартную библиотеку, его необходимо установить, выполнив следующую команду:

$ cd /tmp
$ GO111MODULE=on go get golang.org/x/lint/golint

После этого вы можете запустить так:

$ golint foo.go     # Lint foo.go 文件
$ golint .          # Lint 当前目录下的所有文件
$ golint ./...      # Lint 当前目录及其子目录下的所有文件
$ golint ./foo/bar  # Lint ./foo/bar 目录下的所有文件

Сортировка и проверка зависимостей

Прежде чем вносить какие-либо изменения в свой код, я рекомендую вам выполнить следующие две команды, чтобы отсортировать и проверить ваши зависимости:

$ go mod tidy
$ go mod verify

go mod tidyкоманда удалит вашgo.modиgo.sumлюбые неиспользуемые зависимости в файле и обновите файл, включив в него зависимости для всех возможных комбинаций тега сборки/системы/архитектуры (примечание:go run,go test,go buildetc являются «ленивыми» и будут извлекать только пакеты, необходимые для текущего тега сборки/системы/архитектуры. Запуск этой команды перед каждым коммитом облегчит вам определение того, какие изменения кода ответственны за какие зависимости были добавлены или удалены при просмотре истории контроля версий.

Я также рекомендую использоватьgo mod verifyкоманда для проверки того, были ли случайно (или преднамеренно) изменены зависимости на компьютере, потому что они были загружены и не связаны сgo.sumсоответствуют криптографическим хэшам в файле. Выполнение этой команды помогает гарантировать, что используемые зависимости являются именно теми, которые вы ожидаете, и что любые сборки этой фиксации будут воспроизведены позже.

Сборка и развертывание

построить исполняемый файл

Скомпилироватьmainупаковывать и создавать исполняемые двоичные файлы, которые можноgo buildинструмент. Обычно его можно сочетать с-oпараметры, это позволяет вам явно установить выходной каталог и имя двоичного файла следующим образом:

$ go build -o=/tmp/foo .            # 编译当前目录下的包 
$ go build -o=/tmp/foo ./cmd/foo    # 编译 ./cmd/foo 目录下的包

В этих примерахgo buildбудеткомпилироватьуказанный пакет (и любые зависимые пакеты), затем вызовитеЛинкердля создания исполняемого двоичного файла и вывода его на/tmp/foo.

Примечательно, что начиная с Go 1.10,go buildинструменты впостроить кешкэшируется. Этот кеш будет повторно использоваться в соответствующие моменты будущих сборок, что может значительно ускорить общее время сборки. Это новое поведение кэширования означает «использованиеgo installзаменятьgo buildулучшить кеш"старые правилаБольше не применяется.

Если вы не уверены, где находится кеш сборки, вы можете сделать это, запустивgo env GOCACHEКоманда для проверки:

$ go env GOCACHE
/home/alex/.cache/go-build

Есть ведро, использующее кеш сборкиВажное предупреждение- он не будет обнаружен сcgoИзменения в импортированных библиотеках C. Итак, если ваш код проходитcgoимпортируйте библиотеку C, и вы изменили ее с момента последней сборки, вам нужно использовать-aпараметр для принудительной пересборки всех пакетов. В качестве альтернативы вы можете использоватьgo cleanчтобы очистить кеш:

$ go build -a -o=/tmp/foo .     # 强制重新构建所有包
$ go clean -cache               # 移除所有构建缓存

Примечание: запуститьgo clean -cacheТакже удаляет тестовый кеш.

если ты правgo buildЕсли вас интересует процесс, выполняемый за кулисами, вы можете использовать следующую команду:

$ go list -deps . | sort -u     # 列出在构建可执行文件过程中用到的所有包
$ go build -a -x -o=/tmp/foo .  # 全部重新构建,并展示运行的所有命令

Наконец, если выmainзапустить на пакетеgo build, он будет скомпилирован во временном месте, а результат снова будет сохранен в кэше сборки. Этот процесс не генерирует исполняемый файл.

перекрестная компиляция

Это одна из моих любимых функций Go.

по умолчанию,go buildвыведет двоичные файлы, подходящие для вашей текущей операционной системы и архитектуры. Но он также поддерживает кросс-компиляцию, поэтому вы можете создавать двоичные файлы, подходящие для использования на разных машинах. Это особенно полезно, если вы разрабатываете в одной ОС, а развертываете в другой.

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

$ GOOS=linux GOARCH=amd64 go build -o=/tmp/linux_amd64/foo .
$ GOOS=windows GOARCH=amd64 go build -o=/tmp/windows_amd64/foo.exe .

Если вы хотите увидеть все поддерживаемые операционные системы и архитектуры, вы можете запуститьgo tool dist list:

$ go tool dist list
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/386
darwin/amd64
...

Совет: вы можете использовать кросс-компиляцию GoСоздайте бинарный файл WebAssembly.

Для получения более подробной информации о кросс-компиляции рекомендуется прочитатьэта замечательная статья.

Использование флагов компилятора и компоновщика

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

$ go tool compile -help

Один параметр, который может вас заинтересовать, это-m, который запускает печать информации о решениях по оптимизации, принятых во время компиляции. Вы можете использовать его следующим образом:

$ go build -gcflags="-m -m" -o=/tmp/foo . # 打印优化决策信息

В приведенном выше примере я дважды использовал-mпараметр, что означает, что я хочу распечатать информацию о решении для двух уровней глубины. Если используется только один, можно получить более простой вывод.

Кроме того, начиная с Go 1.10, аргументы компилятора доступны только для передачи вgo buildконкретный пакет - в приведенном выше примере это пакет в текущем каталоге (по.Выражать). Если вы хотите распечатать информацию о решениях по оптимизации для всех пакетов (включая зависимости), вы можете использовать следующую команду:

$ go build -gcflags="all=-m" -o=/tmp/foo .

Начиная с Go 1.11 вы найдетеОтладка оптимизированных двоичных файловЛегче, чем когда-либо. Но вы все равно можете использовать параметры, если это необходимо-Nчтобы отключить оптимизацию, используйте-lчтобы отключить встраивание. Например:

$ go build -gcflags="all=-N -l" -o=/tmp/foo .  # Disable optimizations and inlining

Вы можете просмотреть список доступных параметров ссылки, выполнив следующую команду:

$ go tool link -help

Вероятно, самым известным из них является-XПараметры, которые позволяют вам «вставлять» (строковые) значения в определенные переменные в вашем приложении. Это обычно используется дляДобавить номер версии или зафиксировать хэш. Например:

$ go build -ldflags="-X main.version=1.2.3" -o=/tmp/foo .

Связанный-XДля получения дополнительной информации о параметрах и примере кода см.этот вопрос StackOverflowиэта статья.

Вы также можете быть заинтересованы в использовании-sи-wпараметр для удаления отладочной информации из двоичного файла. Обычно это сокращает 25% от окончательного размера. Например:

$ go build -ldflags="-s -w" -o=/tmp/foo .  # 从二进制文件中删除调试信息

Примечание. Если вам нужно оптимизировать размер исполняемого файла, вам может понадобиться использоватьupxсжать его. Подробнее см.эта статья.

Диагностика проблем и оптимизация

Запустите и сравните тесты

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

Для запуска бенчмарка вам нужно использоватьgo testинструмент, воля-benchВ качестве параметра задано регулярное выражение, соответствующее тесту, который вы хотите выполнить. Например:

$ go test -bench=. ./...                        # 进行基准检查和测试
$ go test -run=^$ -bench=. ./...                # 只进行基准检查,不测试
$ go test -run=^$ -bench=^BenchmarkFoo$ ./...   # 只进行 BenchmarkFoo 的基准检查,不进行测试

я почти всегда использую-benchmemдля запуска эталонного теста, который принудительно включает статистику выделения памяти в выходные данные.

$  go test -bench=. -benchmem ./...

По умолчанию каждый бенчмарк запускается один раз.наименеесекундочку. ты можешь использовать-benchtimeи-countпараметры для его изменения:

$ go test -bench=. -benchtime=5s ./...       # 每个基准测试运行最少 5 秒
$ go test -bench=. -benchtime=500x ./...     # 运行每个基准测试 500 次
$ go test -bench=. -count=3 ./...            # 每个基准测试重复三次以上

Если вы выполняете тестируемый код одновременно, вы можете использовать-cpuпараметры для просмотра измененийGOMAXPROCSВлияние значения на производительность (по сути, количество потоков ОС, которые могут одновременно выполнять код Go). Например, чтобыGOMAXPROCSУстановите 1, 4 и 8, чтобы запустить тест:

$ go test -bench=. -cpu=1,4,8 ./...

Чтобы сравнить изменения между тестами, вы можете использоватьbenchcmpинструмент. это не стандартGoчасть команды, поэтому вам нужно установить ее следующим образом:

$ cd /tmp
$ GO111MODULE=on go get golang.org/x/tools/cmd/benchcmp

Затем вы можете использовать его следующим образом:

$ go test -run=^$ -bench=. -benchmem ./... > /tmp/old.txt
# 做出改变
$ go test -run=^$ -bench=. -benchmem ./... > /tmp/new.txt
$ benchcmp /tmp/old.txt /tmp/new.txt
benchmark              old ns/op     new ns/op     delta
BenchmarkExample-8     21234         5510          -74.05%

benchmark              old allocs     new allocs     delta
BenchmarkExample-8     17             11             -35.29%

benchmark              old bytes     new bytes     delta
BenchmarkExample-8     8240          3808          -53.79%

Анализ и отслеживание

Go может создавать диагностику для использования ЦП, использования памяти, блокировки горутин и конфликтов мьютексов.конфигурационный файл. Вы можете использовать их, чтобы копнуть глубже и точно увидеть, как ваше приложение использует (или ожидает) ресурсы.

Существует три способа создания файлов конфигурации:

  • Если у вас есть веб-приложение, вы можете импортироватьnet/http/pprofСумка. Это будет использоватьhttp.DefaultServeMuxЗарегистрируйте несколько обработчиков, которые затем можно будет использовать для создания и загрузки файлов конфигурации для запущенных приложений.эта статьяХорошее объяснение и пример кода.
  • Для других типов приложений вы можете использоватьpprof.StartCPUProfile()иpprof.WriteHeapProfile()функция для профилирования запущенного приложения. Пример кода см.runtime/pprofдокументация.
  • Или вы можете использовать различные-***profileПараметры генерируют файл конфигурации следующим образом:
$ go test -run=^$ -bench=^BenchmarkFoo$ -cpuprofile=/tmp/cpuprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -memprofile=/tmp/memprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -blockprofile=/tmp/blockprofile.out .
$ go test -run=^$ -bench=^BenchmarkFoo$ -mutexprofile=/tmp/mutexprofile.out .

Примечание. Используйте при выполнении эталонных тестов или тестов.-***profileАргумент выводит тестовые двоичные файлы в текущий каталог. Если вы хотите вывести его в другом месте, вы должны использовать-oпараметры следующим образом:

$ go test -run=^$ -bench=^BenchmarkFoo$ -o=/tmp/foo.test -cpuprofile=/tmp/cpuprofile.out .

Независимо от того, как вы решите создать профиль, когда профиль включен, ваша программа Go будет приостанавливаться примерно 100 раз в секунду и делать снимок в этот момент. Этиобразецсобраны вместе, чтобы сформироватьконтур,ты можешь использоватьpprofинструменты для анализа.

Мой любимый способ проверить файл конфигурации — использоватьgo tool pprof -httpкоманда, чтобы открыть его в веб-браузере. Например:

$ go tool pprof -http=:5000 /tmp/cpuprofile.out

Это будет отображаться по умолчаниюДиаграмма, который показывает дерево выполнения выборочного аспекта приложения, что позволяет быстро понять любые «горячие» ресурсы использования. На приведенном выше графике мы видим, что горячие точки с точки зрения использования ЦП находятся вioutil.ReadFile()из двух системных вызовов.

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

Если объем информации слишком велик, вы можете использовать--nodefractionпараметр для игнорирования узлов, которые составляют менее определенного процента выборки. Например, чтобы игнорировать узлы, которые появляются менее чем в 10% выборок, вы можете запустить так:pprof:

$ go tool pprof --nodefraction=0.1 -http=:5000 /tmp/cpuprofile.out

Это делает график более «зашумленным», если выувеличьте этот скриншот, вы можете более четко увидеть и понять горячие точки, используемые процессором.

Анализ и оптимизация использования ресурсов — это большая и сложная проблема, и здесь я коснулся только ее поверхности. Если вам интересно узнать больше, я предлагаю вам прочитать следующие статьи:

Еще один инструмент, который вы можете использовать для диагностики проблемы, этоТрассировщик выполнения во время выполнения. Это дает вам представление о том, как Go создает и планирует запуск горутин при запуске сборщика мусора, а также информацию о блокировании системных вызовов/сетевых операций/операций синхронизации.

Точно так же вы можете генерировать трассировки из тестов или эталонных тестов или использоватьnet/http/pprofСоздайте и загрузите трассировки для своего веб-приложения. Затем вы можете использоватьgo tool traceПросмотрите результат в веб-браузере следующим образом:

$ go test -run=^$ -bench=^BenchmarkFoo$ -trace=/tmp/trace.out .
$ go tool trace /tmp/trace.out

Важно: в настоящее время можно просматривать только в Chrome/Chromium.

Дополнительные сведения о трассировщике выполнения Go и о том, как интерпретировать вывод, см.Выступление Риса Хилтнера на dotGo 2016иОтличный пост в блоге.

Обнаружение конкуренции

Ранее я говорил об использовании во время тестированияgo test -raceВключите обнаружение гонки Go. Однако вы также можете включить его для запуска программы при сборке исполняемого файла, например:

$ go build -race -o=/tmp/foo .

Особенно важно, что двоичный файл с включенным обнаружением гонки будет использовать больше ЦП и памяти, чем обычно, поэтому его не следует использовать при сборке двоичного файла для производства в обычных условиях.-raceпараметр.

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

По умолчанию, если во время работы двоичного файла будет обнаружено какое-либо состояние гонки, журнал будет записанstderr. При необходимости вы можете использоватьGORACEпеременная среды, чтобы изменить этот параметр. Например, для запуска в/tmp/fooдвоичные файлы и выводить любые журналы гонок в/tmp/race.<pid>,ты можешь использовать:

$ GORACE="log_path=/tmp/race" /tmp/foo

Управление зависимостями

ты можешь использоватьgo listИнструмент проверяет, имеет ли конкретная зависимость обновленную версию, следующим образом:

$ go list -m -u github.com/alecthomas/chroma
github.com/alecthomas/chroma v0.6.2 [v0.6.3]

Это выведет имя зависимости и версию, которую вы используете в настоящее время, или квадратные скобки, если существует более новая версия.[]последняя версия в . вы также можете использоватьgo listчтобы проверить наличие обновлений для всех зависимостей (и подзависимостей) следующим образом:

$ go list -m -u all

ты можешь использоватьgo getКоманда обновляет зависимости до последней версии, адаптированной к версии для определенного тега или хэша, следующим образом:

$ go get github.com/foo/bar@latest
$ go get github.com/foo/bar@v1.2.3
$ go get github.com/foo/bar@7e0369f

Если зависимости, которые вы хотите обновить, имеютgo.modфайл, то в соответствии с этимgo.modИнформация в файле также будет загружена в любойдочерние зависимостиобновление. При использованииgo get -uпараметр,go.modСодержимое файла будет проигнорировано, а все подзависимости будут обновлены до последней дополнительной версии/исправления, даже если они уже установлены.go.modДругая версия указана в .

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

$ go mod tidy
$ go test all

Иногда может понадобиться использовать локальные версии зависимостей (например, перед слиянием патчей в облаке нужно использовать локальную ветку). Для этого вы можете использоватьgo mod editкоманда будетgo.modЗависимости в файле заменяются локальными версиями. Например:

$ go mod edit -replace=github.com/alexedwards/argon2id=/home/alex/code/argon2id

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

File: go.mod

module alexedwards.net/example

go 1.12

require github.com/alexedwards/argon2id v0.0.0-20190109181859-24206601af6c

replace github.com/alexedwards/argon2id => /home/alex/Projects/playground/argon2id

Когда оно больше не нужно, вы можете удалить правило замены с помощью:

$ go mod edit -dropreplace=github.com/alexedwards/argon2id

ты можешь использоватьsame general techniqueИмпортироватьсуществует только в вашей собственной файловой системеупаковка. Это полезно, если вы одновременно работаете над несколькими разрабатываемыми модулями, когда один модуль зависит от другого.

Примечание: если вы не хотите использоватьgo mod editкоманду, вы также можете вручную отредактироватьgo.modфайл, чтобы внести эти изменения. Оба пути возможны.

обновить до новой версии

go fixЭтот инструмент был первоначально выпущен в 2011 году (при этом в API Go все еще вносятся регулярные изменения), чтобы помочь пользователям автоматически обновлять устаревший код, чтобы он был совместим с последней версией Go. С тех пор ГоОбязательство совместимостиозначает, что если вы обновитесь с версии Go 1.x до более новой версии Go 1.x, все должно работать нормально, и обычно нет необходимости использоватьgo fix

Однако по некоторым конкретным вопросамgo fixЭто сработало. Вы можете сделать это, запустивgo tool fix -helpдля просмотра обзора команд. Если вы решите после обновления вам нужно запуститьgo fix, вы должны запустить следующую команду и проверить различия ваших изменений перед фиксацией.

$ go fix ./...

сообщить о проблеме

Если вы уверены, что нашли незарегистрированные проблемы в стандартной библиотеке, инструментах и ​​документации Go, вы можете использоватьGo bugкоманда, чтобы зарегистрировать новую проблему Github.

$ go bug

Откроется страница заполнения проблемы с системной информацией и шаблонами отчетов.

Шпаргалка

Обновлено 2019-04-19:@FedirFRСделал шпаргалку по этой статье. Ты сможешьнажмите сюда для того, чтобы скачать.

Если вам понравилась эта статья, не забудьте ознакомиться с моей новой книгой How ToСоздавайте профессиональные веб-приложения с помощью Go".

Вы можете подписаться на меня в Твиттере@ajmedwards.

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

Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.


Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.