- Оригинальный адрес:An Overview of Go's Tooling
- Оригинальный автор:Alex Edwards
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:iceytea
- Корректор:jianboy, cyril
Меня иногда спрашивают:«Почему вам нравится использовать Go?»Я часто упоминаю об этомgo
Инструментальные команды, которые являются частью языка. Есть некоторые команды - напримерgo fmt
иgo build
-- Я использую его каждый день, и некоторые команды -- напримерgo tool pprof
- Я использую их для решения конкретных задач. Но в любом случае я ценю то, что команда go упрощает управление моим проектом и его обслуживание.
В этом посте я надеюсь предоставить некоторую предысторию и контекст команд, которые я считаю наиболее полезными, и, что более важно, объяснить, как они вписываются в рабочий процесс типичного проекта. Если вы новичок в Go, я надеюсь, что это хорошее начало.
Если вы давно используете Go, эта статья может быть не для вас, но, надеюсь, вы найдете здесь команды и параметры, о которых раньше не знали 😀
Информация в этой статье была написана для Go 1.12 и предполагает, что вы разрабатываетеmodule-enabledс проект.
- установить команду
- Просмотр информации об окружающей среде
- развивать
- контрольная работа
- предварительная проверка
- Сборка и развертывание
- Диагностика проблем и оптимизация
- Управление зависимостями
- обновить до новой версии
- сообщить о проблеме
- Шпаргалка
установить команду
В этой статье я в основном сосредоточусь на части команды 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 build
etc являются «ленивыми» и будут извлекать только пакеты, необходимые для текущего тега сборки/системы/архитектуры. Запуск этой команды перед каждым коммитом облегчит вам определение того, какие изменения кода ответственны за какие зависимости были добавлены или удалены при просмотре истории контроля версий.
Я также рекомендую использовать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
- Отладка проблем с производительностью в программах Go
- Ежедневная оптимизация кода с использованием тестов и аналитики
- Профилирование программ Go с помощью pprof
Еще один инструмент, который вы можете использовать для диагностики проблемы, этоТрассировщик выполнения во время выполнения. Это дает вам представление о том, как 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,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.