Perintah go vet hanya mengawasi pola bahaya yang disepakati resmi dan berkeyakinan tinggi, sehingga banyak masalah kualitas lolos: fungsi yang tidak pernah dipanggil, perbandingan berlebihan dengan konstanta boolean, atau kode yang bisa diringkas tanpa kehilangan makna. staticcheck mengisi ruang itu sebagai linter pihak ketiga paling berpengaruh di ekosistem Go — proyeknya telah bertahun-tahun menjadi acuan sebelum akhirnya sebagian idenya terserap ke toolchain resmi. Pada chapter ini kita akan menginstal staticcheck dari sumbernya, menjalankannya pada program yang tampak sehat tetapi menyimpan dua masalah tersembunyi, lalu memperbaiki temuan sampai pemeriksaan bersih.
Apa yang Diperiksa staticcheck #
staticcheck mengelompokkan ratusan pemeriksaannya ke dalam beberapa keluarga kode. Setiap temuan selalu diakhiri kode kategori dalam tanda kurung sehingga kita bisa melacak dokumentasinya:
| Keluarga | Contoh | Fokus pemeriksaan |
|---|---|---|
SA | SA4006 | Indikasi bug nyata: nilai dihitung lalu tidak pernah dipakai |
S | S1002 | Penyederhanaan: perbandingan x == true cukup ditulis x |
ST | ST1003 | Gaya dan penamaan: nama identifier yang kurang deskriptif |
U | U1000 | Kode mati: fungsi atau field yang tidak pernah diakses |
QF | QF1008 | Saran perbaikan cepat untuk fitur editor |
Keluarga SA dan U paling berharga untuk keandalan program, sedangkan S dan ST menjaga agar basis kode tetap ringkas dan mudah dibaca. staticcheck juga memahami analisis alur data secara dangkal — inilah yang memunguskannya menandai nilai yang dihitung tapi tidak pernah dibaca, sesuatu yang mustahil bagi pemeriksa sintaks biasa.
Instalasi dari Module #
staticcheck didistribusikan sebagai module honnef.co/go/tools dan diinstal lewat go install. Karena instalasi mengompilasi seluruh sumbernya, prosesnya memakan waktu beberapa menit — pada lingkungan penulisan chapter ini, perintah berikut selesai dalam batas 180 detik:
go install honnef.co/go/tools/cmd/staticcheck@latestSetelah selesai, binary staticcheck tersedia di $GOBIN dan bisa memperkenalkan dirinya:
staticcheck -versionOutput yang Dihasilkan:
staticcheck 2026.2.2 (0.8.2)Demo Nyata: Dua Temuan pada Program yang Berjalan Baik #
Kita siapkan modul uji example.com/staticdemo berisi program di bawah ini. Program ini mengompilasi mulus dan keluarannya benar — dua masalahnya hanya terlihat oleh linter:
package main
import "fmt"
func hitungDiskon(harga int, member bool) int {
if member == true {
return harga / 10
}
return 0
}
func rasioDiskon() float64 {
return 0.1
}
func main() {
diskon := hitungDiskon(500000, true)
fmt.Println("Diskon:", diskon)
}Jalankan staticcheck pada seluruh package:
staticcheck ./...Output yang Dihasilkan:
sederhana.go:6:5: should omit comparison to bool constant, can be simplified to member (S1002)
sederhana.go:12:6: func rasioDiskon is unused (U1000)Perintah keluar dengan status 1 karena ada temuan. Dua temuan tersebut kita bedah satu per satu:
sederhana.go:6:5 ... (S1002): perbandinganmember == trueberlebihan. Nilaimembermemang sudah bertipe bool, sehingga kondisi cukup ditulisif member. Kode berlebih seperti ini menambah kebisingan tanpa menambah makna.sederhana.go:12:6 ... (U1000): fungsirasioDiskondideklarasikan tetapi tidak pernah dipanggil dari mana pun. staticcheck menelusuri seluruh package untuk memastikan tidak ada pemanggil, lalu menandainya sebagai kode mati — kandidat kuat untuk dihapus agar pembaca tidak menyangka fungsinya dipakai.
Memilih Sebagian Aturan Saja #
staticcheck dapat dibatasi pada keluarga atau kode tertentu lewat flag -checks. Mode ini berguna saat tim memulai adopsi bertahap — misalnya membereskan dulu kategori penyederhanaan sebelum menyalakan seluruh aturan:
staticcheck -checks S1002 ./...Output yang Dihasilkan:
sederhana.go:6:5: should omit comparison to bool constant, can be simplified to member (S1002)Dengan filter tersebut hanya temuan S1002 yang muncul; temuan U1000 tidak dicek. Nilai filter juga menerima pola seperti S1* untuk seluruh keluarga penyederhanaan.
Perbaikan dan Verifikasi #
Perbaikan keduanya kecil: kondisi diringkas menjadi if member, dan fungsi rasioDiskon dipakai di main karena memang layak dipakai. Berkas contoh.go pada bagian bawah halaman memuat versi hasil perbaikan. Seluruh berkas berbunyi:
package main
import "fmt"
func hitungDiskon(harga int, member bool) int {
if member {
return harga / 10
}
return 0
}
func rasioDiskon() float64 {
return 0.1
}
func main() {
diskon := hitungDiskon(500000, true)
rasio := rasioDiskon()
fmt.Println("Diskon:", diskon, "rasio:", rasio)
}Pada modul uji, versi yang identik menghasilkan pemeriksaan bersih — staticcheck ./... tidak mencetak apa pun dan keluar dengan status 0 — lalu program berjalan normal:
go run contoh.goOutput yang Dihasilkan:
Diskon: 50000 rasio: 0.1Satu perintah staticcheck ./... kini menjaga kebersihan level package. Namun proyek nyata biasanya membutuhkan beberapa linter sekaligus — errcheck, gosec, gofmt — dan mengelola instalasinya satu per satu melelahkan. Chapter berikutnya memperkenalkan golangci-lint yang mengagregasi semuanya dalam satu perintah.
Referensi #
- staticcheck — situs resmi — dokumentasi seluruh aturan beserta contohnya.
- Dokumentasi perintah go vet — pembanding pemeriksa bawaan toolchain.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
contoh.go
Unduh berkaspackage main
import "fmt"
func hitungDiskon(harga int, member bool) int {
if member {
return harga / 10
}
return 0
}
func rasioDiskon() float64 {
return 0.1
}
func main() {
diskon := hitungDiskon(500000, true)
rasio := rasioDiskon()
fmt.Println("Diskon:", diskon, "rasio:", rasio)
}