Alat Bantu

go vet, staticcheck, dan golangci-lint.

Daftar isi

Kompilator Go menolak program yang keliru secara sintaks dan tipe, tetapi banyak masalah lain lolos dari kompilasi dan baru muncul saat program berjalan. Topik ini membahas alat bantu pemeriksaan statis, yaitu pemeriksa yang membaca kode tanpa menjalankannya, mulai dari gofmt dan go vet yang menyertai distribusi Go sampai staticcheck dan golangci-lint yang dipasang terpisah. Contoh gofmt dan go vet dieksekusi nyata pada folder kerja di /tmp, sedangkan dua alat yang tidak terpasang pada lingkungan ini dibahas dengan perintah yang ditandai tidak-dijalankan.

gofmt: format tanpa perdebatan#

Alat gofmt memformat kode sesuai gaya baku bahasa Go, sehingga proyek Go dari penulis mana pun tampil nyaris identik tanpa perdebatan tentang selera. Perintah gofmt menerima berkas maupun folder dan menawarkan tiga mode utama, yaitu gofmt -l yang mencantumkan berkas yang belum rapi, gofmt -d yang menampilkan selisih format, dan gofmt -w yang langsung menuliskan perbaikan pada berkas. Berkas berikut sengaja ditulis dengan perapian yang tidak baku, satu baris tanpa indentasi dan satu baris berindentasi spasi:

go Contoh: berkas dengan perapian yang belum baku
// tidak-dijalankan: berkas disiapkan di /tmp pada blok di bawah
package main

import "fmt"

func main() {
fmt.Println("satu")
        fmt.Println("dua")
}
bash
# siapkan folder eksperimen gofmt
rm -rf /tmp/alat-gofmt
mkdir -p /tmp/alat-gofmt
cd /tmp/alat-gofmt
# tulis berkas dengan perapian yang sengaja tidak baku
cat > main.go <<'EOF'
package main

import "fmt"

func main() {
fmt.Println("satu")
        fmt.Println("dua")
}
EOF
# cantumkan berkas yang belum sesuai format
gofmt -l .
# tampilkan selisih perapian tanpa mengubah berkas
gofmt -d main.go
# terapkan perapian langsung ke berkas
gofmt -w main.go
# daftar ulang, kini tidak ada berkas yang tersisa
gofmt -l .
text Keluaran
main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,6 +3,6 @@
 import "fmt"

 func main() {
-fmt.Println("satu")
-        fmt.Println("dua")
+	fmt.Println("satu")
+	fmt.Println("dua")
 }

gofmt -l mencantumkan main.go, sedangkan gofmt -d menampilkan selisih dalam bentuk diff, yaitu format standar yang barisnya diawali tanda minus untuk isi lama dan tanda tambah untuk isi baru. Indentasi spasi diganti tab dan kedua baris cetakan diseragamkan. Setelah gofmt -w berjalan, daftar berkas yang belum rapi menjadi kosong sehingga perintah terakhir tidak mencetak apa pun. Banyak editor memanggil gofmt secara otomatis saat berkas disimpan, sehingga format baku tetap terjaga tanpa langkah manual.

go vet: pemeriksaan yang menyertai distribusi#

Perintah go vet memeriksa kategori kekeliruan yang sah secara sintaks tetapi hampir pasti salah secara maksud. Salah satu contohnya adalah argumen Printf yang tidak cocok dengan verb formatnya, yaitu penanda seperti %d atau %s pada string format. Kategori lain mencakup penyalinan nilai yang memuat lock, yaitu kunci yang mengatur akses bersama seperti sync.Mutex, dan kode yang tidak akan pernah tercapai. Pemeriksaan vet juga dijalankan secara otomatis pada sebagian pemeriksaan oleh go test, sehingga kelalaian yang sama terkadang tertangkap lebih dulu oleh pengujian. Program berikut sengaja memakai verb %d untuk argumen string:

go Contoh: berkas dengan verb format yang keliru
// tidak-dijalankan: berkas disiapkan di /tmp pada blok di bawah
package main

import "fmt"

func main() {
	nama := "citra"
	fmt.Printf("nama: %d\n", nama)
}
bash
# siapkan folder eksperimen go vet
rm -rf /tmp/alat-vet
mkdir -p /tmp/alat-vet
cd /tmp/alat-vet
# tulis berkas yang sengaja memakai verb format yang keliru
cat > main.go <<'EOF'
package main

import "fmt"

func main() {
	nama := "citra"
	fmt.Printf("nama: %d\n", nama)
}
EOF
# jalankan go vet terhadap berkas tersebut
go vet main.go
# status keluar blok dikembalikan ke nol setelah demo error sengaja
true
text Keluaran
main.go:7:20: fmt.Printf format %d has arg nama of wrong type string

Temuan ditulis satu baris berisi nama berkas, baris, kolom, lalu penjelasannya, dan status keluar go vet menjadi bukan nol. Kompilasi program yang sama tetap berhasil karena tipe argumennya sah, sehingga kekeliruan semacam ini hanya tertangkap oleh pemeriksaan statis. Perbaikannya adalah mengganti verb menjadi %s, dan setelah perbaikan itu go vet tidak lagi mencetak apa pun. Karena alat ini menyertai distribusi Go, pemeriksaannya lazim dijadikan langkah tetap sebelum kode digabung.

staticcheck: pemeriksa pihak ketiga yang populer#

staticcheck adalah kumpulan pemeriksa yang jauh lebih luas daripada go vet dan dipasang terpisah melalui go install. Temuannya dikelompokkan dengan kode kategori, misalnya kategori SA untuk kekeliruan yang nyaris pasti salah, kategori S untuk penyederhanaan yang mungkin, dan kategori ST untuk kepatuhan gaya. Alat ini tidak terpasang pada lingkungan topik ini, sehingga perintahnya hanya ditampilkan sebagai gambaran:

bash
# tidak-dijalankan: staticcheck tidak terpasang di sandbox
# pemasangan memerlukan jaringan untuk mengunduh modulnya
go install honnef.co/go/tools/cmd/staticcheck@latest
# jalankan seluruh pemeriksa terhadap paket-paket modul
staticcheck ./...

Bentuk temuan yang nyaris pasti dilaporkan adalah nilai yang ditetapkan tetapi tidak pernah dibaca, seperti pada fungsi berikut:

go Contoh: nilai yang ditetapkan tetapi tidak pernah dipakai
// tidak-dijalankan: contoh bentuk temuan staticcheck
func rekap() string {
	pesan := "rekap harian"
	return "rekap harian"
}

Variabel pesan tidak berpengaruh apa pun terhadap nilai kembalian, dan pemeriksa menyebutnya dengan nomor baris beserta kode kategorinya. Daftar lengkap kategori beserta contoh temuan tersimpan di situs staticcheck.dev, sehingga setiap temuan dapat ditelusuri alasannya, bukan diperbaiki dengan menebak. Bila satu temuan memang tidak relevan bagi proyek, baris yang bersangkutan dikecualikan dengan komentar penanda milik alatnya, bukan dengan mematikan seluruh pemeriksanya.

golangci-lint: banyak pemeriksa, satu konfigurasi#

golangci-lint tidak menambah pemeriksa baru, melainkan menjalankan puluhan pemeriksa pihak ketiga dalam satu proses, termasuk staticcheck, lalu merapikan seluruh keluarannya menjadi satu laporan. Kegunaan utamanya adalah konfigurasi tunggal, yaitu berkas .golangci.yml pada akar proyek yang memuat daftar pemeriksa yang diaktifkan beserta pengecualian bagi baris tertentu. Alat ini juga tidak terpasang pada lingkungan topik ini:

bash
# tidak-dijalankan: golangci-lint tidak terpasang di sandbox
# instalasi mengikuti petunjuk resmi pada golangci-lint.run
golangci-lint run ./...

Perintah golangci-lint run ./... menjalankan sekumpulan pemeriksa aktif terhadap seluruh paket modul dan mencetak temuan yang dikelompokkan per berkas. Daftar pemeriksa bawaannya sudah terkurasi, dan praktik yang umum adalah membiarkan bawaan itu lalu menambah pemeriksa lain secara bertahap, karena mengaktifkan semuanya sekaligus menghasilkan laporan yang sulit ditindaklanjuti. Pada repositori yang dipakai bersama, perintah yang sama dijadikan langkah pemeriksaan otomatis, sehingga temuan baru muncul sebelum kode digabung, bukan sesudahnya. Dengan berkas konfigurasi yang sama, seluruh anggota tim dan pemeriksa otomatis pada repositori menjalankan aturan yang persis sama.

Kesalahan umum#

Tiga kekeliruan berikut paling sering muncul saat alat bantu diterapkan.

  1. Menganggap build berhasil berarti bebas masalah. Kompilator menolak kekeliruan tipe, tetapi verb format yang tidak cocok dan kode yang tak tercapai lolos begitu saja. go vet dijadikan langkah tetap, misalnya dijalankan bersama pengujian.
  2. Menyerahkan format kepada mata. Selisih gaya antar anggota tim membesarkan perubahan yang perlu ditinjau dan mengaburkan perubahan yang penting. gofmt -w dijalankan sebelum kode digabung, dan editor disetel memanggil gofmt saat berkas disimpan.
  3. Mengaktifkan seluruh pemeriksa pada golangci-lint sekaligus. Laporan yang penuh temuan kecil membuat temuan penting tenggelam. Daftar bawaan yang terkurasi dipakai lebih dahulu, lalu ditambah satu per satu sesuai kebutuhan proyek.

Ringkasan#

  • gofmt menyatukan format kode melalui -l, -d, dan -w, sehingga gaya tidak lagi menjadi perkara selera.
  • go vet menangkap kategori kekeliruan yang lolos kompilasi, seperti verb format yang tidak cocok dengan tipe argumennya.
  • staticcheck memperluas pemeriksaan dengan kode kategori, sedangkan golangci-lint menjalankan banyak pemeriksa dengan satu konfigurasi.
  • Dua alat terakhir dipasang terpisah dan memerlukan jaringan, sehingga contoh perintahnya ditandai tidak-dijalankan pada topik ini.

Referensi#