Jika review pull request di proyek Go Fiber sering tersendat karena hal-hal berulang seperti formatting, import yang berantakan, variabel tidak terpakai, atau error handling yang lolos, masalahnya biasanya bukan pada reviewer, tetapi pada kurangnya pemeriksaan otomatis sebelum kode dikirim. Pre-commit dan golangci-lint membantu memindahkan masalah-masalah dasar ini ke mesin, sehingga reviewer bisa fokus ke logika bisnis, desain API, dan dampak perubahan.
Pendekatan yang efektif untuk tim Go Fiber adalah: jalankan pemeriksaan cepat di mesin developer sebelum commit, lalu jalankan pemeriksaan yang lebih lengkap di pipeline. Dengan begitu, umpan balik tetap cepat, standar kode konsisten, dan CI tidak dipenuhi kegagalan yang seharusnya sudah tertangkap lebih awal.
Mengapa proyek Go Fiber perlu pre-commit dan golangci-lint
Di layanan HTTP berbasis Fiber, perubahan kecil bisa menyentuh banyak lapisan: handler, validasi input, middleware, service, repository, dan test. Tanpa standar otomatis, tim biasanya mengalami beberapa masalah berulang:
- Formatting tidak konsisten, misalnya hasil edit manual atau file yang belum dijalankan
gofmt. - Import berantakan, ada import yang tidak terpakai atau urutan import berubah-ubah.
- Error handling tidak konsisten, misalnya hasil fungsi diabaikan, atau
errtidak dicek dengan baik. - Review melambat karena reviewer mengomentari hal mekanis yang sebenarnya bisa diperiksa otomatis.
- CI menjadi gerbang pertama, sehingga developer baru tahu ada masalah setelah push, bukan saat masih bekerja lokal.
golangci-lint berguna karena ia menggabungkan banyak linter dalam satu perintah dan satu file konfigurasi. Sementara itu, pre-commit berguna untuk memastikan pemeriksaan dasar dijalankan sebelum commit benar-benar dibuat.
Tujuan utamanya bukan membuat aturan sebanyak mungkin, tetapi memastikan standar minimal tim ditegakkan secara konsisten dengan waktu tunggu yang masuk akal.
Struktur file yang disarankan
Untuk proyek Go Fiber, struktur berikut cukup umum dan mudah dirawat:
your-project/
├── cmd/
│ └── api/
│ └── main.go
├── internal/
│ ├── handler/
│ ├── middleware/
│ ├── service/
│ └── repository/
├── pkg/
├── test/
├── .golangci.yml
├── .git/hooks/
├── scripts/
│ ├── pre-commit.sh
│ └── lint-changed.sh
├── Makefile
└── go.modTidak semua repo perlu folder scripts, tetapi memisahkan skrip dari hook Git langsung biasanya lebih mudah dirawat. Hook cukup memanggil skrip, sementara logika sesungguhnya ada di file shell yang bisa ditinjau seperti file lain.
Konfigurasi golangci-lint yang relevan untuk API Fiber
Konfigurasi ideal berbeda untuk tiap tim, tetapi ada pola aman untuk memulai: aktifkan linter yang membantu kualitas dasar dan deteksi bug umum, lalu hindari aturan yang terlalu agresif di tahap awal.
Contoh file .golangci.yml
run:
timeout: 5m
tests: true
issues:
max-issues-per-linter: 0
max-same-issues: 0
exclude-use-default: false
linters:
disable-all: true
enable:
- errcheck
- govet
- ineffassign
- staticcheck
- unused
- gosimple
- gofmt
- goimports
- revive
linters-settings:
revive:
ignore-generated-header: true
rules:
- name: var-naming
- name: indent-error-flow
- name: empty-block
- name: unreachable-code
- name: error-return
issues:
exclude-rules:
- path: _test\.go
linters:
- errcheck
- path: internal/handler/.*\.go
text: "unused-parameter"
Beberapa alasan pemilihan linter di atas:
- gofmt memastikan format standar Go.
- goimports merapikan import sekaligus menghapus yang tidak dipakai.
- errcheck mendeteksi hasil fungsi yang mengembalikan error tetapi diabaikan.
- govet membantu menemukan pola yang mencurigakan secara semantik.
- staticcheck berguna untuk bug umum dan antipola yang sering tidak terlihat saat review.
- ineffassign mendeteksi assignment yang tidak pernah dipakai.
- unused membantu membersihkan simbol yang tidak digunakan.
- revive fleksibel untuk aturan gaya dan kebiasaan tim.
Pada proyek Fiber, aturan seperti unused-parameter kadang perlu dikecualikan pada handler tertentu jika ada parameter yang harus sesuai kontrak antarmuka atau pola middleware. Intinya, konfigurasi harus membantu, bukan memaksa tim menulis kode yang jadi lebih buruk hanya untuk memuaskan linter.
Catatan penting untuk handler Fiber
Pola handler Fiber sering terlihat seperti ini:
func (h *UserHandler) GetByID(c *fiber.Ctx) error {
id := c.Params("id")
user, err := h.service.GetByID(c.Context(), id)
if err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
return c.JSON(user)
}Pada titik ini, linter paling berguna untuk API biasanya bukan linter gaya yang terlalu detail, tetapi linter yang menangkap:
- error yang diabaikan,
- kode tidak terpakai,
- kondisi yang bisa disederhanakan,
- potensi bug semantik,
- formatting dan import yang konsisten.
Untuk tahap awal adopsi, ini sudah memberi dampak besar tanpa terlalu banyak gesekan.
Membuat pre-commit lokal yang cepat dan tidak mengganggu
Kesalahan umum saat memasang hook adalah menjalankan seluruh test suite dan seluruh lint untuk seluruh repo setiap commit. Hasilnya biasanya hook dimatikan oleh developer karena terlalu lambat. Strategi yang lebih sehat adalah:
- Pre-commit lokal: cepat, fokus pada file yang berubah.
- Pipeline CI: lengkap, mencakup seluruh repo.
Skrip pre-commit sederhana
Simpan skrip berikut di scripts/pre-commit.sh:
#!/usr/bin/env sh
set -eu
CHANGED_GO_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$' || true)
if [ -z "$CHANGED_GO_FILES" ]; then
exit 0
fi
echo "Menjalankan gofmt dan goimports pada file yang berubah..."
for file in $CHANGED_GO_FILES; do
[ -f "$file" ] || continue
gofmt -w "$file"
goimports -w "$file"
done
echo "Menambahkan ulang file yang diubah formatter ke staging..."
for file in $CHANGED_GO_FILES; do
[ -f "$file" ] || continue
git add "$file"
done
echo "Menjalankan lint cepat pada paket yang relevan..."
golangci-lint run --new-from-rev=HEAD
Lalu buat hook Git di .git/hooks/pre-commit:
#!/usr/bin/env sh
exec ./scripts/pre-commit.shPastikan keduanya dapat dieksekusi:
chmod +x scripts/pre-commit.sh
chmod +x .git/hooks/pre-commitPendekatan ini bekerja karena:
gofmtdangoimportsdijalankan hanya untuk file Go yang sedang di-stage.- file hasil format ditambahkan ulang ke staging agar commit berisi versi yang sudah dirapikan.
golangci-lint run --new-from-rev=HEADmembatasi fokus ke perubahan baru, sehingga lebih cepat dibanding lint seluruh repo.
Jika tim tidak ingin mengandalkan pemasangan manual di .git/hooks, Anda bisa menyediakan target Makefile atau skrip bootstrap untuk menginstalnya. Yang penting, cara instalasinya konsisten dan terdokumentasi.
Kapan hook sebaiknya gagal
Hook pre-commit sebaiknya menggagalkan commit ketika:
- formatter mengubah file dan developer perlu meninjau hasilnya, atau
- lint menemukan masalah yang harus diperbaiki.
Namun ada dua pendekatan:
- Strict: setelah formatter mengubah file, hook gagal dan meminta developer commit ulang. Ini lebih eksplisit.
- Convenient: formatter jalan, file di-add ulang, lalu hook lanjut ke lint. Ini lebih cepat untuk alur harian.
Untuk tim kecil sampai menengah, pendekatan kedua biasanya lebih nyaman selama perubahan otomatis tetap mudah dipahami.
Integrasi dengan Makefile
Makefile membantu menyeragamkan perintah lint di semua mesin. Jangan biarkan tiap developer mengingat kombinasi perintah sendiri.
.PHONY: fmt lint lint-fast test install-hooks
fmt:
gofmt -w .
goimports -w .
lint:
golangci-lint run
lint-fast:
golangci-lint run --new-from-rev=HEAD
test:
go test ./...
install-hooks:
mkdir -p .git/hooks
cp scripts/pre-commit.sh .git/hooks/pre-commit
chmod +x .git/hooks/pre-commitDengan Makefile seperti ini, dokumentasi onboarding jadi lebih sederhana:
make install-hooks
make lint-fast
make lintAnda juga bisa meminta CI menggunakan target yang sama agar perintah lokal dan pipeline tidak menyimpang. Ini mengurangi kasus “lolos lokal, gagal di CI” karena perintah yang dijalankan berbeda.
Strategi lint cepat di mesin developer dan lint penuh di pipeline
Ini bagian yang sering menentukan apakah adopsi berhasil atau tidak. Jika semua lint dijalankan setiap commit untuk seluruh repo, performa akan terasa berat, terutama pada repo lama atau monorepo kecil yang terus tumbuh.
Lint cepat di developer machine
Tujuannya adalah memberi umpan balik dalam hitungan detik atau setidaknya tetap terasa ringan. Fokus utamanya:
- formatting dan import,
- lint untuk perubahan baru,
- opsional: test untuk paket yang berubah jika biayanya masih masuk akal.
Contoh perintah yang cocok untuk lokal:
make lint-fastAtau jika perlu lebih konservatif, jalankan hanya formatter pada pre-commit lalu lint saat pre-push atau sebelum membuka pull request. Pilihan ini berguna jika repo Anda besar dan waktu lint masih terlalu lama.
Lint penuh di pipeline
Di CI, jalankan pemeriksaan lebih lengkap:
golangci-lint rununtuk seluruh repo,go test ./...,- opsional pemeriksaan tambahan sesuai kebutuhan tim.
Alasannya sederhana: mesin developer dioptimalkan untuk kecepatan umpan balik, sedangkan pipeline dioptimalkan untuk memastikan kualitas keseluruhan repositori. Keduanya punya peran berbeda, dan tidak perlu memikul beban yang sama.
Prinsip praktis: lokal harus cepat cukup untuk mencegah masalah umum, sedangkan CI harus lengkap cukup untuk melindungi branch utama.
Trade-off aturan lint yang terlalu ketat
Menambah banyak linter tidak otomatis menaikkan kualitas. Aturan yang terlalu ketat sering menimbulkan efek samping:
- False positive meningkat, developer mulai mengabaikan output linter.
- Kode menjadi kaku, ditulis untuk menyenangkan alat, bukan untuk kejelasan.
- Onboarding melambat, terutama untuk anggota tim yang baru pindah ke Go.
- Waktu perbaikan membengkak untuk masalah gaya yang dampaknya kecil.
Beberapa gejala konfigurasi terlalu ketat:
- banyak pengecualian inline seperti
//nolinttanpa penjelasan, - PR kecil dipenuhi perbaikan kosmetik,
- developer mematikan hook lokal,
- perdebatan lebih sering soal aturan alat daripada desain kode.
Solusinya bukan membuang lint, tetapi memilih aturan yang paling berguna dahulu. Untuk proyek Go Fiber yang berfokus pada API backend, prioritas awal biasanya:
- formatting dan import,
- error handling,
- deteksi bug umum,
- simbol tidak terpakai,
- sedikit aturan gaya yang memang disepakati tim.
Aturan gaya yang terlalu subjektif sebaiknya datang belakangan, setelah tim sudah nyaman dengan fondasi dasarnya.
Rollout bertahap untuk repo lama
Repo lama hampir selalu punya dua tantangan: banyak temuan historis dan tidak semua bagian aktif dikerjakan. Jika Anda langsung mengaktifkan semua linter untuk seluruh repositori, adopsi biasanya macet.
Pendekatan yang lebih aman
- Mulai dari linter inti:
gofmt,goimports,errcheck,govet,staticcheck,unused. - Fokus pada kode baru: gunakan lint berbasis perubahan di lokal.
- Perbaiki temuan historis per area, misalnya mulai dari
internal/handlerlaluservice. - Izinkan pengecualian sementara pada folder lama yang belum sempat dibersihkan.
- Kurangi pengecualian secara berkala saat area tersebut disentuh.
Contoh strategi yang umum dipakai:
- minggu pertama: pasang formatter + import + lint cepat untuk kode baru,
- minggu berikutnya: aktifkan lint penuh di CI dengan beberapa exclude rules,
- setelah stabil: hapus pengecualian yang tidak lagi diperlukan.
Pendekatan ini lebih realistis daripada memaksa “bersih total” dalam satu kali perubahan besar, yang justru menyulitkan review dan berisiko konflik merge di banyak branch aktif.
Kapan menggunakan pengecualian
Pengecualian masih masuk akal jika:
- kode lama belum disentuh tetapi terlalu bising untuk dibersihkan sekarang,
- ada pola framework atau antarmuka yang memang tidak cocok dengan aturan tertentu,
- biaya perbaikan saat ini lebih besar daripada manfaat langsungnya.
Namun hindari pengecualian permanen tanpa catatan. Beri komentar atau dokumentasi singkat mengapa aturan itu dikecualikan, sehingga tim paham bahwa itu keputusan sadar, bukan kelalaian.
Kesalahan umum saat implementasi
1. Mengira formatter saja sudah cukup
gofmt dan goimports memang penting, tetapi keduanya tidak menggantikan linter semantik. Masalah seperti error yang diabaikan atau assignment tidak efektif tidak akan selalu tertangkap hanya dengan formatter.
2. Menjalankan semua lint pada setiap commit
Ini cepat membuat hook terasa lambat. Developer akhirnya mencari cara untuk melewati hook. Lebih baik pre-commit ringan dan CI lengkap.
3. Tidak menyamakan perintah lokal dan CI
Jika lokal memakai satu set perintah dan CI memakai yang lain, hasilnya tidak konsisten. Gunakan Makefile atau skrip yang sama sebanyak mungkin.
4. Terlalu banyak nolint
//nolint tanpa alasan akan menjadi hutang teknis. Jika memang perlu, sertakan alasan singkat agar reviewer bisa menilai apakah pengecualian itu layak.
5. Mengubah seluruh repo hanya untuk formatting
Pada repo aktif, perubahan massal seperti ini bisa memperbesar konflik merge. Lebih aman melakukannya per area atau pada momen yang terkontrol.
Tips debugging saat hook atau lint bermasalah
- Jalankan skrip hook secara manual untuk melihat error lengkap:
./scripts/pre-commit.sh. - Pastikan tool terpasang:
golangci-lint,goimports, dan Go toolchain tersedia di PATH. - Cek file yang benar-benar di-stage dengan
git diff --cached --name-only. - Bandingkan hasil lokal dan CI untuk memastikan perintah dan konfigurasi sama.
- Periksa timeout jika lint besar sering berhenti terlalu cepat; sesuaikan secara wajar di konfigurasi.
- Uji aturan exclude dengan hati-hati, karena pola path atau regex yang keliru sering membuat issue tetap muncul atau justru terlalu banyak dikecualikan.
Checklist adopsi tim
Gunakan daftar ini agar implementasi pre-commit dan golangci-lint di proyek Go Fiber berjalan rapi:
- Tentukan tujuan awal: kurangi noise review, bukan mencari semua pelanggaran sekaligus.
- Sepakati linter inti yang wajib untuk semua orang.
- Buat file
.golangci.ymlyang sederhana dan bisa dijelaskan. - Sediakan skrip pre-commit yang cepat untuk file atau perubahan baru.
- Tambahkan target Makefile untuk
fmt,lint-fast, danlint. - Gunakan perintah yang sama di lokal dan CI sebisa mungkin.
- Dokumentasikan cara instalasi hook di onboarding proyek.
- Batasi penggunaan
//nolintdan minta alasan singkat. - Untuk repo lama, rollout bertahap dengan pengecualian sementara yang jelas.
- Tinjau ulang konfigurasi setelah beberapa sprint: aturan mana yang berguna, mana yang hanya menambah friksi.
Penutup
Untuk tim yang mengembangkan API dengan Go Fiber, kombinasi pre-commit dan golangci-lint adalah cara praktis menjaga kualitas sebelum kode masuk CI. Nilai utamanya bukan sekadar kode terlihat rapi, tetapi mengurangi pekerjaan mekanis saat review, mempercepat umpan balik, dan membuat standar tim lebih konsisten.
Mulailah dari aturan yang paling berdampak: formatting, import, error handling, dan deteksi bug umum. Setelah alur kerja stabil dan tim sudah nyaman, barulah tambahkan aturan lain secara bertahap. Pendekatan yang moderat hampir selalu lebih berhasil daripada konfigurasi yang langsung terlalu ketat.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!