Предупреждение
Nilaway в настоящее время находится в активной разработке: могут произойти ложные срабатывания и нарушение изменений. Мы очень ценим любые отзывы и вклад!
Nilaway - это статический инструмент анализа, который стремится помочь разработчикам избежать паники NIL в производстве, ловив их во время компиляции, а не во время выполнения. Nilaway похож на стандартный анализатор Nilness, однако, он использует гораздо более сложные и мощные методы статического анализа для отслеживания потоков NIL в пакете, а также в разных пакетах, и сообщать об ошибках, предоставляющих пользователям потоки Nilness для облегчения отладки.
Нилауэй пользуется тремя ключевыми свойствами, которые выделяют его:
Он полностью автоматизирован : Nilaway оснащен двигателем вывода, что не требует никакой дополнительной информации от разработчиков (например, аннотаций), помимо стандартного кода GO.
Это быстро : мы разработали Nilaway, чтобы быть быстрым и масштабируемым, что делает его подходящим для больших кодовых баз. В наших измерениях мы наблюдали менее чем 5% накладных расходов, когда Nilaway включен. Мы также постоянно применяем оптимизации, чтобы еще больше уменьшить его след.
Это практично : это не предотвращает всю возможную панику NIL в вашем коде, но он улавливает большую часть потенциальной паники NIL, которую мы наблюдали в производстве, позволяя Nilaway поддерживать хороший баланс между полезностью и накладными расходами на строительство.
? Для получения более подробной технической дискуссии, пожалуйста, проверьте наш Wiki, Engineering Blog и Paper (WIP).
Nilaway реализуется с использованием стандартного анализа GO/, что позволяет легко интегрироваться с существующими драйверами анализатора (то есть Golangci-Lint, Nogo или работа в качестве автономного контроля).
Важный
По умолчанию Nilaway Analyse All Go Code, включая стандартные библиотеки и зависимости. Это помогает Nilaway лучше понять зависимости формы кода и уменьшить его ложные негативы. Тем не менее, это также понесло бы значительную стоимость производительности (только один раз для драйверов с модульной поддержкой) и увеличило бы количество несвязанных ошибок в зависимостях, для крупных проектов GO с большим количеством зависимостей.
Мы настоятельно рекомендуем использовать флаг include-pkgs, чтобы сузить анализ исключительно кода вашего проекта. Это направляет Nilaway пропустить анализ зависимостей (например, сторонние библиотеки), что позволяет вам сосредоточиться исключительно на потенциальной панике NIL, сообщенной Nilaway в вашем первом личном коде!
Важный
Из -за изысканности анализа, которые делает Nilaway, Nilaway кэширует свои выводы о конкретном пакете с помощью механизма факта из структуры GO/анализа. Таким образом, настоятельно рекомендуется использовать драйвер, который поддерживает модульный анализ (IE, Bazel/Nogo или Golangci-Lint, но не автономный контрол, поскольку он хранит все факты в памяти) для лучшей производительности в крупных проектах. Автономный контрол предоставляется больше для целей оценки, так как его легко начать.
Установите двоичный файл из источника, работая:
go install go.uber.org/nilaway/cmd/nilaway@latestЗатем запустите Linter по:
nilaway -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Кончик
Отключите флаг pretty-print при выходе как JSON:
nilaway -json -pretty-print=false -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Nilaway, в своей нынешней форме, может сообщать о ложных положительных моментах. К сожалению, это препятствует его непосредственному слиянию в Голангчи-Линте и предлагается в качестве Линтера (см. PR#4045). Поэтому вам необходимо создать Nilaway в качестве плагина для Golangci-Lint, который будет выполняться в качестве частного Линтера. В Golangci-Lint есть две системы плагинов, и гораздо проще использовать систему плагинов модуля (представленная с V1.57.0), и это единственный поддерживаемый подход для запуска Nilaway в Golangci-Lint.
(1) Создайте файл .custom-gcl.yml в корне репозитория, если вы этого не сделали, добавьте следующее содержание:
# This has to be >= v1.57.0 for module plugin system support.
version : v1.57.0
plugins :
- module : " go.uber.org/nilaway "
import : " go.uber.org/nilaway/cmd/gclplugin "
version : latest # Or a fixed version for reproducible builds. (2) Добавить Nilaway в файл конфигурации Linter .golangci.yaml :
linters-settings :
custom :
nilaway :
type : " module "
description : Static analysis tool to detect potential nil panics in Go code.
settings :
# Settings must be a "map from string to string" to mimic command line flags: the keys are
# flag names and the values are the values to the particular flags.
include-pkgs : " <YOUR_PACKAGE_PREFIXES> "
# NilAway can be referred to as `nilaway` just like any other golangci-lint analyzers in other
# parts of the configuration file.(3) Создайте пользовательский бинар Golangci-Lint с Nilaway, включенным:
# Note that your `golangci-lint` to bootstrap the custom binary must also be version >= v1.57.0.
$ golangci-lint custom По умолчанию будет построен пользовательский двоичный файл . с именем custom-gcl , который может быть дополнительно настроен в файле .custom-gcl.yml (для инструкций см. Систему плагина модуля).
Кончик
Кэшируйте пользовательский двоичный, чтобы избежать необходимости создавать его снова для сохранения ресурсов, вы можете использовать хэш файла .custom-gcl.yml в качестве ключа кэша, если вы используете фиксированную версию Nilaway. Если вы используете latest в качестве версии Nilaway, вы можете добавить дату сборки к ключу кэша, чтобы заставить кэш истечь после определенного периода времени.
(4) Запустите нестандартный двоичный файл вместо golangci-lint :
# Arguments are the same as `golangci-lint`.
$ ./custom-gcl run ./...Бег с Bazel/Nogo требует немного больше усилий. Сначала следуйте инструкциям из Rules_go, Gazelle и Nogo, чтобы настроить свой проект GO, чтобы его можно было построить с Bazel/Nogo без набора Linters NO или по умолчанию. Затем,
(1) Добавить import _ "go.uber.org/nilaway" в свой файл tools.go Go (или другой файл, который вы используете для настройки зависимостей инструмента, см. Как я могу отслеживать зависимости инструмента для модуля? Из документации GO Modules), чтобы избежать go mod tidy с удаления Nilaway в качестве зависимости инструмента.
(2) Запустите следующие команды, чтобы добавить Nilaway в качестве зависимости от инструментов в ваш проект:
# Get NilAway as a dependency, as well as getting its transitive dependencies in go.mod file.
$ go get go.uber.org/nilaway@latest
# This should not remove NilAway as a dependency in your go.mod file.
$ go mod tidy
# Run gazelle to sync dependencies from go.mod to WORKSPACE file.
$ bazel run //:gazelle -- update-repos -from_file=go.mod (3) Добавить Nilaway в конфигурации Nogo (обычно в файле BUILD.bazel ):
nogo(
name = "my_nogo",
visibility = ["//visibility:public"], # must have public visibility
deps = [
+++ "@org_uber_go_nilaway//:go_default_library",
],
config = "config.json",
) (4) Запустите Bazel Build, чтобы увидеть, как работал Nilaway (любая ошибка nogo остановит сборку Bazel, вы можете использовать флаг --keep_going , чтобы запросить Bazel для построения как можно большего):
$ bazel build --keep_going //...(5) См. Документацию Nogo о том, как передать конфигурацию JSON для драйвера Nogo, и посмотрите на нашу страницу вики о том, как передавать конфигурации в Nilaway.
Давайте посмотрим на несколько примеров, чтобы увидеть, как Nilaway может помочь предотвратить панику NIL.
// Example 1:
var p * P
if someCondition {
p = & P {}
}
print ( p . f ) // nilness reports NO error here, but NilAway does. В этом примере локальная переменная p инициализируется только тогда, когда someCondition верно. На полевом доступе pf может возникнуть паника, если someCondition неверно. Nilaway может поймать этот потенциальный поток NIL и сообщает о следующей ошибке, показывающей этот поток Nilness:
go.uber.org/example.go:12:9: error: Potential nil panic detected. Observed nil flow from source to dereference point:
- go.uber.org/example.go:12:9: unassigned variable `p` accessed field `f`
Если мы охраняем этот размер с помощью проверки нильнеса ( if p != nil ), ошибка исчезнет.
Nilaway также может ловить потоки NIL по функциям. Например, рассмотрим следующий фрагмент кода:
// Example 2:
func foo () * int {
return nil
}
func bar () {
print ( * foo ()) // nilness reports NO error here, but NilAway does.
} В этом примере функция foo возвращает нулевой указатель, который непосредственно привязан к bar , что приводит к панике, когда называется bar . Nilaway может поймать этот потенциальный поток NIL и сообщать о следующей ошибке, описывая поток Nilness через границы функций:
go.uber.org/example.go:23:13: error: Potential nil panic detected. Observed nil flow from source to dereference point:
- go.uber.org/example.go:20:14: literal `nil` returned from `foo()` in position 0
- go.uber.org/example.go:23:13: result 0 of `foo()` dereferenced
Обратите внимание, что в приведенном выше примере foo не обязательно должен проживать в том же пакете, что и bar . Nilaway также может отслеживать потоки NIL через пакеты. Кроме того, Nilaway обрабатывает языковые конструкции, такие как приемники, интерфейсы, утверждения типа, переключатели типа и многое другое.
Мы выставляем набор флагов с помощью стандартного механизма прохождения флагов в GO/Analysis. Пожалуйста, проверьте Wiki/Configuration, чтобы увидеть доступные флаги и как их передавать, используя разные драйверы Linter.
Мы следуем той же политике поддержки версий, что и проект GO: мы поддерживаем и проверяем последние две основные версии GO.
Пожалуйста, не стесняйтесь открывать проблему GitHub, если у вас есть какие -либо вопросы, отчеты об ошибках и запросы функций.
Мы хотели бы, чтобы вы внесли свой вклад в Nilaway! Обратите внимание, что после того, как вы создадите запрос на привлечение, вам будет предложено подписать наше лицензионное соглашение Uber.
Этот проект Copyright 2023 Uber Technologies, Inc., и лицензирован в Apache 2.0.