คำเตือน
Nilaway กำลังอยู่ระหว่างการพัฒนาที่ใช้งานอยู่: ผลบวกที่ผิดพลาดและการเปลี่ยนแปลงที่เกิดขึ้นสามารถเกิดขึ้นได้ เราขอขอบคุณข้อเสนอแนะและการมีส่วนร่วมใด ๆ !
Nilaway เป็นเครื่องมือการวิเคราะห์แบบคงที่ที่พยายามช่วยให้นักพัฒนาหลีกเลี่ยงความตื่นตระหนกในการผลิตโดยการจับพวกเขาในเวลาที่รวบรวมแทนที่จะรันไทม์ อย่างไรก็ตาม Nilaway นั้นคล้ายคลึงกับเครื่องวิเคราะห์ NILNESS มาตรฐานอย่างไรก็ตามใช้เทคนิคการวิเคราะห์แบบคงที่ที่ซับซ้อนและทรงพลังมากขึ้นเพื่อติดตามการไหลของ NIL ภายในแพ็คเกจรวม ถึง แพ็คเกจและรายงานข้อผิดพลาดที่ทำให้ผู้ใช้มีกระแสไฟ
Nilaway มีคุณสมบัติสำคัญสามประการที่ทำให้โดดเด่น:
มันเป็น แบบอัตโนมัติ : Nilaway ติดตั้งเอ็นจิ้นการอนุมานทำให้ ไม่ จำเป็นต้องมีข้อมูลเพิ่มเติมใด ๆ จากนักพัฒนา (เช่นคำอธิบายประกอบ) นอกเหนือจากรหัส GO มาตรฐาน
มัน เร็ว : เราได้ออกแบบ Nilaway ให้เร็วและปรับขนาดได้ทำให้เหมาะสำหรับฐานรหัสขนาดใหญ่ ในการวัดของเราเราได้สังเกตค่าใช้จ่ายในการสร้างเวลาน้อยกว่า 5% เมื่อเปิดใช้งาน Nilaway นอกจากนี้เรายังใช้การปรับให้เหมาะสมอย่างต่อเนื่องเพื่อลดรอยเท้าต่อไป
มัน ใช้งานได้จริง : มันไม่ได้ป้องกันความตื่นตระหนกที่เป็นไปได้ ทั้งหมด ในรหัสของคุณ แต่มันจับความตื่นตระหนกที่อาจเกิดขึ้นส่วนใหญ่ที่เราสังเกตเห็นในการผลิตทำให้ Nilaway รักษาสมดุลระหว่างประโยชน์และค่าใช้จ่ายในการสร้าง
- สำหรับการอภิปรายทางเทคนิคโดยละเอียดเพิ่มเติมโปรดตรวจสอบ Wiki บล็อกวิศวกรรมและกระดาษ (WIP) ของเรา
Nilaway ดำเนินการโดยใช้ GO/การวิเคราะห์มาตรฐานทำให้ง่ายต่อการรวมเข้ากับไดรเวอร์เครื่องวิเคราะห์ที่มีอยู่ (เช่น Golangci-Lint, Nogo หรือทำงานเป็นตัวตรวจสอบแบบสแตนด์อโลน)
สำคัญ
โดยค่าเริ่มต้น Nilaway วิเคราะห์รหัส GO ทั้งหมด รวมถึงไลบรารีมาตรฐานและการพึ่งพา สิ่งนี้จะช่วยให้ Nilaway เข้าใจการพึ่งพาแบบฟอร์มรหัสและลดเชิงลบที่ผิดพลาดได้ดีขึ้น อย่างไรก็ตามสิ่งนี้จะต้องเสียค่าใช้จ่ายที่สำคัญ (เพียงครั้งเดียวสำหรับผู้ขับขี่ที่ได้รับการสนับสนุนแบบแยกส่วน) และเพิ่มจำนวนข้อผิดพลาดที่ไม่สามารถตอบสนองได้ในการพึ่งพาสำหรับโครงการ GO ขนาดใหญ่ที่มีการพึ่งพาจำนวนมาก
เราขอแนะนำให้ใช้การตั้งค่าสถานะรวม PKGS เพื่อ จำกัด การวิเคราะห์รหัสโครงการของคุณโดยเฉพาะ สิ่งนี้นำไปสู่ Nilaway เพื่อข้ามการวิเคราะห์การพึ่งพา (เช่นห้องสมุดบุคคลที่สาม) ช่วยให้คุณสามารถมุ่งเน้นไปที่ความตื่นตระหนกที่อาจเกิดขึ้นโดย Nilaway ในรหัสบุคคลแรกของคุณ!
สำคัญ
เนื่องจากความซับซ้อนของการวิเคราะห์ที่ Nilaway ทำ Nilaway ทำให้การค้นพบเกี่ยวกับแพ็คเกจเฉพาะผ่านกลไกความเป็นจริงจากกรอบการวิเคราะห์/การวิเคราะห์ ดังนั้นจึง ขอ แนะนำให้ใช้ประโยชน์จากไดรเวอร์ที่รองรับการวิเคราะห์แบบแยกส่วน (เช่น 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 และนำเสนอเป็น linter (ดู PR#4045) ดังนั้นคุณต้องสร้าง Nilaway เป็นปลั๊กอินไปยัง Golangci-Lint เพื่อดำเนินการเป็น linter ส่วนตัว มีสองระบบปลั๊กอินใน 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 ต้องใช้ความพยายามมากขึ้นเล็กน้อย ก่อนอื่นให้ทำตามคำแนะนำจาก RULLE_GO, Gazelle และ Nogo เพื่อตั้งค่าโครงการ GO ของคุณเพื่อให้สามารถสร้างขึ้นด้วย Bazel/Nogo โดยไม่มีการกำหนดค่าชุดลายทาง แล้ว,
(1) เพิ่ม import _ "go.uber.org/nilaway" ลงในไฟล์ tools.go ของคุณ (หรือไฟล์อื่น ๆ ที่คุณใช้สำหรับการกำหนดค่าการพึ่งพาเครื่องมือดูวิธีการติดตามเครื่องมือสำหรับการพึ่งพาเครื่องมือสำหรับโมดูลจากเอกสารโมดูล 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) เรียกใช้ Bazel Build เพื่อดูการทำงานของ Nilaway (ข้อผิดพลาดใด ๆ ของ NOGO จะหยุด Bazel Build คุณสามารถใช้ธง --keep_going กำลังขอให้ Bazel สร้างให้มากที่สุด):
$ bazel build --keep_going //...(5) ดูเอกสารเกี่ยวกับวิธีการผ่านการกำหนดค่า 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 ส่งคืนตัวชี้ NIL ซึ่งถูกเรียกใช้โดยตรงใน 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 Flows ข้ามแพ็คเกจได้เช่นกัน ยิ่งไปกว่านั้น Nilaway จัดการกับการสร้างภาษาที่เฉพาะเจาะจงเช่นตัวรับสัญญาณอินเทอร์เฟซการยืนยันประเภทสวิตช์ประเภทและอื่น ๆ
เราเปิดเผยชุดของธงผ่านกลไกการส่งธงมาตรฐานในการวิเคราะห์/การวิเคราะห์ โปรดตรวจสอบ wiki/การกำหนดค่าเพื่อดูธงที่มีอยู่และวิธีการส่งผ่านโดยใช้ไดรเวอร์ linter ที่แตกต่างกัน
เราทำตามนโยบายการสนับสนุนเวอร์ชันเดียวกันกับโครงการ GO: เราสนับสนุนและทดสอบสองเวอร์ชันหลักล่าสุดของ GO
โปรดอย่าลังเลที่จะเปิดปัญหา GitHub หากคุณมีคำถามรายงานข้อผิดพลาดและคำขอคุณสมบัติ
เราอยากให้คุณมีส่วนร่วมใน Nilaway! โปรดทราบว่าเมื่อคุณสร้างคำขอดึงคุณจะถูกขอให้ลงนามในข้อตกลงใบอนุญาตผู้สนับสนุน Uber ของเรา
โครงการนี้เป็นลิขสิทธิ์ 2023 Uber Technologies, Inc. และได้รับใบอนุญาตภายใต้ Apache 2.0