บทที่ 22 · Part 6 — Evidence-Driven Quality

Tool-Driven Review

สร้าง feedback loop จาก fmt, vet, static analysis, govulncheck, coverage และ CI matrix

code review ที่ใช้คนตรวจ formatting, unchecked error และ dependency vulnerability ทีละบรรทัดทำให้เวลา สำหรับ contract/ownership หายไป แต่การเปิด linter ทุกตัวพร้อมกันก็สร้าง noise จนทีม ignore ทั้งหมด Feedback loop ที่ดีให้เครื่องทำสิ่ง deterministic และเก็บ judgment ที่สำคัญไว้ให้ reviewer

จบบทนี้คุณจะ

  • แบ่ง quality gates เป็น format, compile/test, analysis, security และ compatibility
  • ใช้ go vet, static analysis และ govulncheck โดยเข้าใจขอบเขต
  • ออกแบบ CI matrix ที่เร็วพอใช้จริงและมี job ลึกสำหรับความเสี่ยงสูง

Feedback Loop จากเร็วไปลึก

local loop ต้องเร็ว: format, compile และ unit tests ของ package ที่แก้ ส่วน CI เพิ่ม whole-module tests, analysis, race, integration, vulnerability และ build artifact อย่ารวมทุกอย่างใน command เดียวจนไม่รู้ว่า failure มาจากชั้นใดและ rerun ทั้ง pipeline ราคาแพง

baseline ที่ทุก module ควรมี:

gofmt -w .
go test ./...
go vet ./...
go mod tidy -diff
go mod verify

go vet ตรวจ pattern ที่น่าสงสัยตาม analyzers ของ Go ไม่ใช่ proof ว่าโปรแกรมถูก เพิ่ม staticcheck หรือ golangci-lint เมื่อทีมเลือก rules, pin version, บันทึกเหตุผลของ exclusion และพร้อมแก้ false positive อย่าตั้ง warnings หลายพันแล้วประกาศว่า “มี lint”

Tool Dependency ต้อง Reproducible

Go 1.24+ รองรับ tool directives ใน go.mod ทำให้ pin generator/analyzer และเรียกผ่าน go tool ได้โดยไม่ปนกับ runtime imports:

go get -tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@v2.8.0
go get -tool golang.org/x/vuln/cmd/govulncheck@latest
go tool oapi-codegen --version
go tool govulncheck ./...

ใน repository จริงควร pin explicit version หลังทดลอง ไม่ปล่อย @latest ใน CI เพราะ build วันนี้กับ เดือนหน้าจะต่างกัน Generated code ต้องมี command เดียว, input ชัด และ CI ตรวจว่า generate แล้วไม่มี diff

Go 1.26 ขยาย go fix ด้วย modernizers ที่ช่วย rewrite code ไป API/pattern ปัจจุบัน ใช้บน branch แล้ว review diff + tests ไม่ถือว่า automatic rewrite ถูกเชิง behavior ทุกกรณี module ที่ baseline 1.25 ต้องระวัง ไม่ให้ rewrite ใช้ API 1.26 ใน core path

Vulnerability, Supply Chain และ License

govulncheck ใช้ call graph ช่วยรายงาน known vulnerabilities ที่ code น่าจะเรียกถึง จึง actionable กว่าดู module versionอย่างเดียว แต่ไม่พบ zero-day, misconfiguration หรือ business authorization bug ต้องอัปเดต vulnerability database/tool และอ่าน advisory ก่อนตัดสิน remediation

ก่อนรับ library ให้ตรวจ maintenance, release cadence, license, module graph, transitive dependencies, API stability และ operational behavior ไม่ใช้ดาวเป็นคะแนนเดียว คำถามสำคัญคือมันแทน code/error surface อะไร และทีมพร้อม update ใครเมื่อ advisory ออก

go list -m -u all
go mod graph
go version -m ./bin/settlement

CI Matrix ที่มีเจตนา

คอร์สนี้กำหนด go 1.25.0 จึงให้ normal unit/build รันบน latest 1.25.x และ 1.26.x อย่างน้อย 1 job ใช้ 1.26 สำหรับ lint/tooling หลัก และมี race job บน platform ที่รองรับ Integration tests แยกด้วย tag หรือ package/suite ไม่ซ่อนว่าต้องใช้ Docker/credentials

Coverage เป็น navigation tool: ดู diff ว่า branch/error path ใดยังไม่มี test ไม่ตั้ง 80% เป็นคำแทนคุณภาพ บาง parser ควรสูงมาก ขณะที่ generated code หรือ adapter บางส่วนให้ contract test มีคุณค่ากว่า

Reviewer ยังต้องตรวจอะไร

เครื่องมือไม่รู้ว่า error chain เปิด driver contract โดยไม่ตั้งใจ, goroutine มี owner หรือไม่, Redis ถูกใช้ ตัดสิน authoritative state หรือ OpenAPI auth scheme ถูก enforce จริงไหม Reviewer ควรใช้เวลาอ่าน call site, failure path, boundaries, limits และ migration plan เมื่อ mechanical checks ผ่านแล้ว

Production Toolbox

Default: Go toolchain (fmt, test, vet, mod) + staticcheck หรือ curated golangci-lint + govulncheck ใช้ gosec เมื่อ threat surface คุ้ม SAST เพิ่ม Pin ทุก tool และแยก fast PR checks จาก scheduled/deep checks โดย failure ที่ merge ได้ต้องมี owner และ expiry

Checklist ของ Quality Gate

  • local fast loop รันง่ายและตรงกับ CI
  • tool/generator versions ถูก pin และ generated diff ถูกตรวจ
  • -race, integration, fuzz และ vulnerability scan มี schedule/owner ชัด
  • supported Go majors อยู่ใน compatibility matrix
  • linter exclusions มีเหตุผลแคบและทบทวนได้
  • dependency ใหม่มี maintenance, license, security และ replacement rationale
  • reviewer ใช้เวลากับ contract, ownership, lifecycle และ limits

อ่านเพิ่ม: go command, Go Vulnerability Management, Integration test coverage และ Go 1.26 release notes