NilAway is a static analysis tool that detects potential nil panics in Go code. It uses sophisticated analysis techniques to track nil flows within and across packages, reporting errors with nilness flows for easier debugging.
make build # Build the nilaway binary to <project root>/bin/make test # Run unit tests for all modules
make cover # Run tests with coverage reports
make integration-test # Run integration tests (using real drivers)Test packages under testdata/src/go.uber.org must use the default configuration and should be
safe to run in parallel. Tests that require special flags must run serially, with their packages
placed directly under testdata/src instead.
The following golden tests are available, which run NilAway on a base (usually main) and test (usually HEAD) branches
on stdlib and compare the differences of NilAway violations. This is mostly run in CI to catch unexpected breakages.
# The arguments are passed as an environment variable `ARGS`.
# Use `make golden-test ARGS="-h" to see the available arguments.
make golden-test ARGS="-base-branch main -test-branch HEAD -result-file /tmp/result.txt"make lint # Run all linting (format check, mod tidy, golangci-lint, nilaway self-check)
make lint-fix # Run all linting with autofix (and auto-formats) appliedThe following subcommands are available if you need to run individual linting components. Pass in FIX=true environment
variable to apply auto-fixes if available.
In most cases you only need to ever run make lint or make lint-fix instead of these.
make format-lint # Check if Go files are correctly formatted
make tidy-lint # Check go.mod tidiness
make golangci-lint # Run golangci-lint only
make nilaway-lint # Run nilaway on itselfRun make upgrade-deps to upgrade all dependencies and tools to their latest versions for all modules within NilAway.
Optionally, set GO_VERSION=<version> environment variable to upgrade to a specific Go version (e.g., 1.21).
# Build nilaway in current codebase.
make build
# Standalone usage
bin/nilaway -include-pkgs="<YOUR_PKG_PREFIX>" ./...
# With JSON output (disable pretty-print)
bin/nilaway -json -pretty-print=false -include-pkgs="<YOUR_PKG_PREFIX>" ./...
# Using custom golangci-lint build
golangci-lint custom # Build custom binary with NilAway plugin
./custom-gcl run ./... # Run custom golangci-lint with NilAwayFor best performance and easier maintenance, NilAway consists of multiple levels of sub-analyzers that are all
analysis.Analyzers, and they are connected by specifying dependencies (via Requires field) between them. Currently, the organization is as follows:
- nilaway.Analyzer (nilaway.go) - Top-level analyzer that reports errors
- accumulation.Analyzer - Collects triggers, runs inference, returns errors
- annotation.Analyzer - Reads annotations from structs/interfaces/functions
- function.Analyzer - Analyzes functions and creates triggers
- anonymousfunc.Analyzer - Handles function literals
- structfield.Analyzer - Handles struct field accesses
- affiliation.Analyzer - Creates interface-struct affiliation triggers
- global.Analyzer - Creates global variable triggers
- accumulation.Analyzer - Collects triggers, runs inference, returns errors
All the analyzers depend on config.Analyzer (config/config.go) to retrieve configurations.
The decoupling of error generation and error reporting logic makes it possible to apply custom error reporting to fit other needs. For example, it is possible to create another top-level analyzer nilaway-log that depends on the accumulation analyzer, which simply retrieves the NilAway errors and logs them to a local file or database for later auditing.
- Triggers: Flow conditions that may cause nil panics
- Annotations: Metadata about nilability of types and functions
- Inference Engine: Matches triggers with annotations to detect nil flows
- Facts Mechanism: Caches analysis results across packages for performance
nilaway.go- Main analyzer entry pointcmd/nilaway/main.go- Standalone checker with additional flagscmd/gclplugin/gclplugin.go- golangci-lint plugin integrationaccumulation/analyzer.go- Core inference coordinationconfig/config.go- Configuration management
-include-pkgs: Comma-separated package prefixes to analyze (recommended)-exclude-pkgs: Package prefixes to exclude from analysis-pretty-print: Enable/disable pretty error messages (default: true)-group-error-messages: Group similar error messages-experimental-struct-init-enable: Enable experimental struct initialization-experimental-anonymous-func-enable: Enable experimental anonymous function support
- Uses
go/analysisFacts mechanism for cross-package caching - For large projects, use modular drivers (bazel/nogo or golangci-lint) over standalone checker
- Recommend using
-include-pkgsto focus analysis on first-party code only
- Root module: Core NilAway implementation
tools/module: Development tools (golden-test, integration-test)testdata/directory: Comprehensive test cases organized by feature
Refer to docs/ directory for more documentations on other aspects of NilAway.