Berkas yang sudah rapi formatnya berkat gofmt masih menyisakan satu sumber kerapian yang kerap dilupakan: blok import. Daftar import yang tidak terurut, import yang sudah tidak terpakai, dan import yang lupa ditulis membuat kompilasi gagal atau code review berkepanjangan. Tool goimports menyelesaikan ketiganya sekaligus: perintah ini mengurutkan import ke urutan standar, membuang import yang tidak digunakan, dan mencari lalu menambahkan import yang hilang. Pada chapter ini kita akan menginstal goimports, lalu mengujinya pada berkas yang daftar import-nya sengaja dibuat berantakan.

Tiga Tugas goimports dalam Satu Perintah #

goimports dibangun di atas mesin gofmt, sehingga seluruh perbaikan format gofmt tetap berlaku, ditambah penataan khusus import:

Masalah pada blok importTindakan goimports
Import tidak terurut alfabetisDiurutkan, stdlib dan pihak ketiga dikelompokkan terpisah
Import dinyatakan tetapi tidak dipakaiDibuang dari blok import
Package dipakai tetapi tidak diimporDicari di module/GOPATH lalu ditambahkan

Karena goimports memformat lebih banyak hal daripada gofmt, banyak tim menjadikan goimports pemformat utama — hasil akhirnya selalu kompatibel dengan pemeriksaan gofmt -l.

Instalasi goimports #

goimports tidak ikut serta dalam distribusi standar Go, tetapi instalasinya hanya satu perintah go install:

bash
go install golang.org/x/tools/cmd/goimports@latest

Perintah tersebut berhasil dijalankan pada lingkungan penulisan chapter ini (prosesnya cepat karena goimports hanya satu modul kecil). Binary hasil instalasi muncul di direktori $GOBIN atau $(go env GOPATH)/bin sehingga goimports dapat dipanggil langsung dari shell:

bash
goimports -h

Output yang Dihasilkan:

text
usage: goimports [flags] [path ...]
  -cpuprofile string
    	CPU profile output
  -d	display diffs instead of rewriting files
  -e	report all errors (not just the first 10 on different lines)
  -format-only
    	if true, don't fix imports and only format. In this mode, goimports is effectively gofmt, with the addition that imports are grouped into sections.
  -l	list files whose formatting differs from goimport's
  -local string
    	put imports beginning with this string after 3rd-party packages; comma-separated list
  -memprofile string
    	memory profile output
  -memrate int
    	if > 0, sets runtime.MemProfileRate
  -srcdir dir
    	choose imports as if source code is from dir. When operating on a single file, dir may instead be the complete file name.
  -trace string
    	trace profile output
  -v	verbose logging
  -w	write result to (source) file instead of stdout

Demo: Mengurutkan dan Membuang Import #

Kita siapkan modul kecil bernama example.com/importdemo dengan satu berkas main.go. Blok import-nya sengaja diacak urutannya (strings duluan, errors menyusup di tengah) dan memuat dua import yang tidak dipakai program:

go
package main

import (
	"strings"
	"errors"
	"fmt"
	"os"
)

func main() {
	nama := strings.TrimSpace("  Budi  ")
	fmt.Println(fmt.Sprintf("Halo, %s!", nama))
}

Program hanya memakai strings dan fmt, sehingga errors dan os akan dibuang. Perintah goimports -l melaporkan berkas yang butuh dirapikan:

bash
goimports -l .

Output yang Dihasilkan:

text
main.go

Sebelum menulis ulang berkas, kita periksa dulu diff yang diusulkan goimports:

bash
goimports -d main.go

Output yang Dihasilkan:

text
diff -u main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -1,10 +1,8 @@
 package main
 
 import (
-	"strings"
-	"errors"
 	"fmt"
-	"os"
+	"strings"
 )
 
 func main() {

Mari kita baca diff di atas baris demi baris:

  1. Baris - "strings" dan + "strings": import strings pindah posisi — dari baris pertama blok ke baris setelah fmt — karena urutan alfabetis menempatkan fmt sebelum strings.
  2. Baris - "errors" dan - "os": kedua import ini dibuang karena program tidak memanggil package errors maupun os sama sekali.
  3. Blok hasil akhir hanya berisi fmt lalu strings: dua baris tersisa itulah satu-satunya package yang benar-benar dipakai.

Menambahkan Import yang Hilang #

Kasus kedua adalah kebalikannya: kita memakai sebuah package tetapi lupa mengimpornya. Berkas sapa.go berikut memanggil strings.TrimSpace padahal blok import hanya memuat fmt:

go
package main

import "fmt"

func sapa(nama string) string {
	return fmt.Sprintf("Halo, %s!", strings.TrimSpace(nama))
}

Dalam kondisi seperti ini kompilasi akan gagal dengan galat undefined: strings. goimports memperbaikinya dengan menambahkan import yang hilang sekaligus mengubah bentuk blok menjadi bentuk berkurung:

bash
goimports -d sapa.go

Output yang Dihasilkan:

text
diff -u sapa.go.orig sapa.go
--- sapa.go.orig
+++ sapa.go
@@ -1,6 +1,9 @@
 package main
 
-import "fmt"
+import (
+	"fmt"
+	"strings"
+)
 
 func sapa(nama string) string {
 	return fmt.Sprintf("Halo, %s!", strings.TrimSpace(nama))

goimports menemukan strings dari standard library secara otomatis. Untuk package pihak ketiga, pencarian dilakukan terhadap module aktif — package yang belum berada di go.mod tetap perlu go get lebih dulu.

Sekarang kita terapkan seluruh perbaikan lalu memverifikasi hasilnya tiga lapis: daftar berkas kotor, kompilasi, dan eksekusi:

bash
goimports -w .
goimports -l .
go run .

Output yang Dihasilkan:

text
Halo, Budi!

Baris goimports -l . tidak mencetak apa pun — semua berkas sudah rapi. Program kemudian berjalan mulus dan mencetak Halo, Budi!, membuktikan penataan import tidak mengubah perilaku program.

Berkas contoh.go pada bagian bawah halaman memperlihatkan hasil akhir proses ini: import berkurut fmt dan strings, tubuh program memakai keduanya. Seluruh berkas berbunyi:

go
package main

import (
	"fmt"
	"strings"
)

func main() {
	nama := strings.TrimSpace("  Budi  ")
	fmt.Printf("Halo, %s!\n", nama)
}

Jalankan berkas tersebut dengan perintah berikut:

bash
go run contoh.go

Output yang Dihasilkan:

text
Halo, Budi!

Dengan format dan import yang terjaga otomatis, saat berikutnya kode dibuka oleh anggota tim lain akan langsung terbaca familiar. Pembersihan tampilan selesai; pemeriksaan kualitas yang mendalam dimulai dari go vet pada chapter berikutnya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh.go

Unduh berkas
go
package main

import (
	"fmt"
	"strings"
)

func main() {
	nama := strings.TrimSpace("  Budi  ")
	fmt.Printf("Halo, %s!\n", nama)
}