警告
Nilawayは現在、積極的な開発中です。誤検知と壊れた変化が起こる可能性があります。どんなフィードバックや貢献も高く評価しています!
Nilawayは、開発者がランタイムではなくコンパイル時にキャッチすることにより、開発者が生産中のパニックを避けるのに役立つ静的分析ツールです。 Nilawayは標準のNilness Analyzerに似ていますが、パッケージ全体でパッケージ内のNILフローを追跡するためにはるかに洗練された強力な静的分析技術を採用し、ユーザーがNilnessフローを提供してデバッグを容易にするエラーを報告します。
Nilawayは、目立つ3つの重要なプロパティを楽しんでいます。
それは完全に自動化されています:Nilawayには推論エンジンが装備されているため、標準のGOコード以外に、開発者からの追加情報(アノテーションなど)は必要ありません。
速いです:私たちは、速くてスケーラブルであるようにNilawayを設計し、大きなコードベースに適しています。測定では、Nilawayが有効になっているときに5%未満のビルドタイムオーバーヘッドが観察されました。また、フットプリントをさらに削減するために、常に最適化を適用しています。
それは実用的です:それはあなたのコード内のすべての可能なゼロパニックを妨げるものではありませんが、それは私たちが生産で観察した潜在的な潜在的なパニックのほとんどを捕らえ、ニラウェイが有用性とビルドタイムのオーバーヘッドの間の良いバランスを維持することを可能にします。
?より詳細な技術的な議論については、Wiki、Engineering Blog、およびPaper(WIP)をご覧ください。
Nilawayは標準のGO/分析を使用して実装されており、既存のアナライザードライバー(IE、Golangci-Lint、NOGO、またはスタンドアロンチェッカーとしての実行)と簡単に統合できます。
重要
デフォルトでは、Nilawayは標準ライブラリや依存関係を含むすべてのGOコードを分析します。これにより、Nilawayはコードフォームの依存関係をよりよく理解し、その偽陰性を軽減するのに役立ちます。ただし、これには、多くの依存関係を持つ大規模なGOプロジェクトで、かなりのパフォーマンスコストが発生し(モジュラーサポートのあるドライバーの場合は1回だけ)、依存関係の非扱い性のないエラーの数が増加します。
includeed-PKGSフラグを使用して、分析をプロジェクトのコード専用に絞り込むことを強くお勧めします。これにより、Nilawayは依存関係の分析(サードパーティライブラリなど)の分析をスキップするように指示し、Nilawayがファーストパーティコードで報告した潜在的なNILパニックのみに焦点を当てることができます。
重要
Nilawayが行う分析の洗練により、NilawayはGO/分析フレームワークからの事実メカニズムを介して特定のパッケージに関する発見をキャッシュします。したがって、大規模プロジェクトでのパフォーマンスを向上させるために、モジュール分析(IE、Bazel/NogoまたはGolangci-Lintをサポートするドライバーを活用することを強くお勧めします(Bazel/NogoまたはGolangci-Lintはすべて、すべての事実を保存するため、スタンドアロンチェッカーではありません)。スタンドアロンチェッカーは、簡単に開始できるため、評価の目的でより提供されます。
実行してソースからバイナリをインストールします。
go install go.uber.org/nilaway/cmd/nilaway@latest次に、次のようにリナーを実行します。
nilaway -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...ヒント
JSONとして出力されるとpretty-printフラグを無効にします。
nilaway -json -pretty-print=false -include-pkgs= " <YOUR_PKG_PREFIX>,<YOUR_PKG_PREFIX_2> " ./...Nilawayは、現在の形式では、誤検知を報告できます。残念ながら、Golangci-Lintでの即時のマージを妨げ、リナーとして提供されます(PR#4045を参照)。したがって、プライベートリナーとして実行されるGolangci-LintのプラグインとしてNilawayを構築する必要があります。 Golangci-Lintには2つのプラグインシステムがあり、モジュールプラグインシステム(v1.57.0以降導入)を使用する方がはるかに簡単で、Golangci-LintでNilawayを実行する唯一のサポートされているアプローチです。
(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)Linter構成ファイルにnilawayを追加します.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)Nilawayを使用してカスタムGolangci-Lintバイナリを構築します。
# 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ファイルでさらにカスタマイズできます(手順については、モジュールプラグインシステムを参照)。
ヒント
カスタムバイナリをキャッシュしてリソースを保存するためにもう一度構築する必要がありません。Nilawayの固定バージョンを使用している場合、 .custom-gcl.ymlファイルのハッシュをキャッシュキーとして使用できます。 Nilawayバージョンとしてlatestを使用している場合は、特定の期間後にキャッシュキーにビルドの日付を追加してキャッシュの有効期限を強制することができます。
(4) golangci-lintの代わりにカスタムバイナリを実行します。
# Arguments are the same as `golangci-lint`.
$ ./custom-gcl run ./...Bazel/Nogoで走るには、少し多くの努力が必要です。まず、Rules_go、Gazelle、およびNogoの指示に従って、GOプロジェクトを設定して、設定されたLinterのデフォルトセットまたはデフォルトのセットでBazel/Nogoで構築できるようにします。それから、
(1) import _ "go.uber.org/nilaway"をtools.goファイル(またはツール依存関係の構成に使用する他のファイル、モジュールのツール依存関係を追跡する方法を参照してください) go mod tidy参照してください。
(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)ベイゼルビルドを実行して、Nilawayが機能するのを見る(NOGOエラーはBazelビルドを停止します。 --keep_goingフラグを使用してBazelを要求してできるだけビルドすることができます):
$ bazel build --keep_going //...(5)構成JSONをNOGOドライバーに渡す方法に関するNOGOドキュメントを参照し、構成をNilawayに渡す方法に関するWikiページを参照してください。
NilawayがNilのパニックを防ぐのにどのように役立つかを見て、いくつかの例を見てみましょう。
// Example 1:
var p * P
if someCondition {
p = & P {}
}
print ( p . f ) // nilness reports NO error here, but NilAway does.この例では、ローカル変数p 、 someCondition真である場合にのみ初期化されます。 Field Access pfでは、 someCondition間違っている場合、パニックが発生する可能性があります。ニラウェイはこの潜在的なニルの流れをキャッチすることができ、このニルネスの流れを示す次のエラーを報告します。
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`
Nilness Check( 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 nilポインターを返します。これは、 barで直接繰り返されるため、 barが呼び出されるたびにパニックになります。 Nilawayはこの潜在的なNilの流れをキャッチし、次のエラーを報告し、関数の境界を介したニレネスの流れを説明します。
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固有の言語コンストラクトを処理します。
GO/分析の標準フラグ通過メカニズムを介して、一連のフラグを公開します。 Wiki/Configurationを確認して、利用可能なフラグを確認し、さまざまなリンジタードライバーを使用してそれらを渡す方法を確認してください。
GOプロジェクトと同じバージョンサポートポリシーに従います。GOの最後の2つの主要バージョンをサポートおよびテストします。
質問、バグレポート、機能のリクエストがある場合は、GitHubの問題を自由に開いてください。
ニラウェイに貢献してほしいです!プルリクエストを作成したら、Uberの寄稿者ライセンス契約に署名するように求められることに注意してください。
このプロジェクトは、著作権2023 Uber Technologies、Inc。であり、Apache 2.0でライセンスされています。