تحذير
نيلواي حاليًا تحت التطوير النشط: يمكن أن تحدث إيجابيات كاذبة وتغييرات كسر. نحن نقدر بشدة أي ردود فعل ومساهمات!
Nilaway هي أداة تحليل ثابت تسعى لمساعدة المطورين على تجنب الذعر في الإنتاج من خلال اصطيادها في وقت التجميع بدلاً من وقت التشغيل. يشبه Nilaway محلل Nilness القياسي ، ومع ذلك ، فإنه يستخدم تقنيات تحليل ثابتة أكثر تطوراً وقوية لتتبع تدفقات NIL داخل حزمة وكذلك عبر الحزم ، والإبلاغ عن الأخطاء التي تزود المستخدمين بتدفقات NILNESS لتسهيل تصحيح الأخطاء.
يتمتع Nilaway بثلاث خصائص رئيسية تجعلها تبرز:
إنه معتمد بالكامل : تم تجهيز Nilaway بمحرك استدلال ، مما يجعله لا يتطلب أي معلومات إضافية من المطورين (على سبيل المثال ، التعليقات التوضيحية) إلى جانب رمز GO القياسي.
إنه سريع : لقد قمنا بتصميم Nilaway لتكون سريعًا وقابل للتطوير ، مما يجعله مناسبًا لأبواب الكود الكبيرة. في قياساتنا ، لاحظنا أقل من 5 ٪ من الوقت في وقت البناء عند تمكين Nilaway. نحن أيضًا نطبق باستمرار تحسينات لزيادة الحد من بصمتها.
إنه عملي : إنه لا يمنع كل الذعر الممكنة في الكود الخاص بك ، لكنه يمسك معظم الذعر المحتملة التي لاحظناها في الإنتاج ، مما يسمح لـ Nilaway بالحفاظ على توازن جيد بين الفائدة ووقت البناء.
؟ لمزيد من المناقشة الفنية التفصيلية ، يرجى مراجعة مدونة Wiki و Engineering و Paper (WIP).
يتم تنفيذ Nilaway باستخدام التحليل/التحليل القياسي ، مما يجعل من السهل الاندماج مع برامج تشغيل المحللين الحالية (أي Golangci-Lint ، Nogo ، أو تشغيل مدقق مستقل).
مهم
بشكل افتراضي ، يقوم Nilaway بتحليل جميع رمز GO ، بما في ذلك المكتبات والتبعيات القياسية. هذا يساعد Nilaway بشكل أفضل على فهم تبعيات شكل الكود وتقليل السلبيات الخاطئة. ومع ذلك ، فإن هذا سيؤدي أيضًا إلى تكلفة أداء كبيرة (مرة واحدة فقط للسائقين الذين لديهم دعم معياري) ويزيد من عدد الأخطاء غير القابلة للاستثمار في التبعيات ، لمشاريع GO الكبيرة مع الكثير من التبعيات.
نوصي بشدة باستخدام علامة تضمين PKGS لتضييق التحليل إلى رمز مشروعك حصريًا. هذا يوجه Nilaway لتخطي تحليل التبعيات (على سبيل المثال ، مكتبات الطرف الثالث) ، مما يتيح لك التركيز فقط على الذعر المحتملة التي أبلغ عنها Nilaway في رمز الطرف الأول!
مهم
نظرًا لتطور التحليلات التي يقوم بها Nilaway ، فإن Nilaway تخزين نتائجها حول حزمة معينة عبر آلية الحقيقة من إطار GO/Analysis. لذلك ، يوصى بشدة بالاستفادة من سائق يدعم التحليل المعياري (أي 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 ، في شكلها الحالي ، الإبلاغ عن إيجابيات كاذبة. هذا للأسف يعيق دمجه الفوري في Golangci-Lint ويتم تقديمه كخطي (انظر PR#4045). لذلك ، تحتاج إلى بناء Nilaway كمساعد لـ Golangci-lint ليتم تنفيذها كخطي خاص. يوجد نظامان إضافيان في Golangci-Lint ، وهو أسهل بكثير لاستخدام نظام Plugin Module (تم تقديمه منذ 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 يتطلب المزيد من الجهود. أولاً ، اتبع الإرشادات من Dorm_Go و Gazelle و Nogo لإعداد مشروع GO الخاص بك بحيث يمكن بناؤه باستخدام 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) Run Bazel Build لرؤية Nilaway يعمل (أي خطأ في Nogo سيوقف بناء البازل ، يمكنك استخدام العلم --keep_going لطلب Bazel لبناء أكبر قدر ممكن):
$ bazel build --keep_going //...(5) راجع وثائق NOGO حول كيفية تمرير تكوين JSON إلى برنامج تشغيل NOGO ، وشاهد صفحة wiki الخاصة بنا حول كيفية تمرير التكوينات إلى Nilaway.
دعونا نلقي نظرة على بعض الأمثلة لنرى كيف يمكن لـ Nilaway المساعدة في منع الذعر.
// 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 قادر على التقاط هذا التدفق غير المحتمل والتقارير عن الخطأ التالي الذي يوضح تدفق 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`
إذا حذرنا هذا الإرهاق من خلال فحص nilness ( if p != nil ) ، فإن الخطأ يزول.
Nilaway قادر أيضًا على التقاط التدفقات عبر الوظائف. على سبيل المثال ، ضع في اعتبارك مقتطف الرمز التالي:
// Example 2:
func foo () * int {
return nil
}
func bar () {
print ( * foo ()) // nilness reports NO error here, but NilAway does.
} في هذا المثال ، تُرجع الوظيفة foo مؤشرًا لا شيء ، والذي يتم ترحيله مباشرة في bar ، مما يؤدي إلى ذعر كلما تم استدعاء bar . Nilaway قادر على التقاط هذا التدفق غير المحتمل والتقارير عن الخطأ التالي ، ووصف تدفق 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/التكوين لرؤية الأعلام المتاحة وكيفية تمريرها باستخدام برامج تشغيل Linter مختلفة.
نتبع نفس سياسة دعم الإصدار مثل مشروع GO: نحن ندعم ونختبر الإصدارين الرئيسيين الأخيرين من GO.
لا تتردد في فتح مشكلة github إذا كان لديك أي أسئلة وتقارير الأخطاء وطلبات الميزة.
نود أن تساهم في Nilaway! يرجى ملاحظة أنه بمجرد إنشاء طلب سحب ، سيُطلب منك توقيع اتفاقية ترخيص مساهم Uber.
هذا المشروع هو حقوق الطبع والنشر 2023 Uber Technologies ، Inc. ، ومرخصة بموجب Apache 2.0.