Program command line sering menerima opsi: nama berkas konfigurasi, jumlah baris keluaran, atau saklar mode verbose. Membaca os.Args secara manual berarti menguraikan string sendiri — rawan salah dan hasilnya berbeda-beda antar program. Package flag bawaan Go menyediakan penguraian standar: deklarasikan flag, panggil flag.Parse, lalu baca nilainya. Chapter ini membangun satu program CLI lengkap dengan pola tersebut.
Mendeklarasikan Flag #
flag.String, flag.Int, dan flag.Bool menerima tiga argumen: nama flag, nilai default, dan teks usage. Ketiganya mengembalikan pointer ke variabel internal yang terisi setelah parsing, sehingga nilai akhirnya dibaca dengan operator *:
nama := flag.String("nama", "tamu", "nama pengguna yang disapa")Pola alternatif tanpa pointer mengisi variabel yang sudah Anda deklarasikan sendiri:
flag.BoolVar(&verbose, "verbose", false, "tampilkan detail ekstra")flag.Parse dan Nilai Default #
flag.Parse membaca os.Args[1:] lalu mengisi seluruh nilai flag. Ketika program dijalankan tanpa argumen, setiap flag memuat nilai defaultnya — program tetap berjalan normal, bukan gagal. Panggil flag.Parse tepat satu kali setelah seluruh deklarasi selesai.
Teks Usage dan PrintDefaults #
flag.PrintDefaults mencetak daftar flag beserta tipe, nilai default, dan teks usage — bantuan yang selaras otomatis dengan deklarasi. Variabel flag.Usage dapat diganti fungsi sendiri untuk mengendalikan seluruh teks bantuan; fungsi inilah yang dipanggil ketika pengguna mengetik -h.
Argumen Posisi #
Penguraian flag berhenti pada tanda --; seluruh sisa argumen menjadi argumen posisi. flag.Args() mengembalikannya sebagai []string, dan flag.Narg() melaporkan jumlahnya. Pola program --jumlah=5 data.txt memisahkan opsi dari sasaran operasinya dengan cara ini.
Flag -h dan Nilai Salah #
Ketika pengguna mengetik -h atau --help, package flag memanggil flag.Usage lalu mengakhiri program dengan exit code 0 — permintaan bantuan bukan galat. Nilai yang gagal dikonversi ke tipe flag memicu pesan galat, flag.Usage dicetak ulang, dan program berhenti dengan exit status 2 sehingga skrip shell dapat mendeteksi penyalahgunaan argumen.
| Perilaku pengguna | Tanggapan package flag | Exit code |
|---|---|---|
-h atau --help | teks usage dicetak | 0 |
| nilai tidak sesuai tipe | galat + teks usage | 2 |
| flag tidak dideklarasikan | galat + teks usage | 2 |
flag vs os.Args Manual #
| Aspek | os.Args manual | package flag |
|---|---|---|
Penguraian --nama=nilai | ditulis sendiri | otomatis |
| Nilai default | ditulis sendiri | bagian deklarasi |
| Teks bantuan | ditulis sendiri | dibangkitkan dari usage text |
| Argumen posisi | penggalan manual | flag.Args() |
Chapter Package os
menunjukkan pembacaan os.Args mentah; untuk CLI nyata, flag menyelesaikan seluruh pekerjaan tersebut. Program bergaya subcommand seperti git clone memerlukan flag.FlagSet — kumpulan flag terpisah per subcommand dengan penguraian dan galatnya sendiri.
Program Utuh #
Berkas flag-demo.go merangkai seluruh materi chapter:
package main
import (
"flag"
"fmt"
"os"
"strings"
)
func main() {
// flag.String, flag.Int, dan flag.Bool mengembalikan pointer ke nilai.
nama := flag.String("nama", "tamu", "nama pengguna yang disapa")
umur := flag.Int("umur", 18, "umur pengguna dalam tahun")
verbose := flag.Bool("verbose", false, "tampilkan detail ekstra")
// Alihkan keluaran package flag ke stdout, lalu cetak teks usage.
flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = func() {
fmt.Println("Cara pakai: go run flag-demo.go [flag] [argumen posisi...]")
flag.PrintDefaults()
}
flag.PrintDefaults()
// flag.Parse membaca argumen command line sebenarnya.
flag.Parse()
fmt.Printf("Halo, %s (umur %d tahun)\n", *nama, *umur)
fmt.Println("verbose :", *verbose)
if sisa := flag.Args(); len(sisa) > 0 {
fmt.Println("posisi :", strings.Join(sisa, ", "))
}
}Jalankan program dari folder chapter tanpa argumen:
go run flag-demo.goOutput yang Dihasilkan:
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
Halo, tamu (umur 18 tahun)
verbose : falseMari kita telaah baris demi baris program di atas:
- Baris 12-14: tiga flag dideklarasikan dengan nilai default dan teks usage; masing-masing mengembalikan pointer.
- Baris 17:
flag.CommandLine.SetOutput(os.Stdout)mengalihkan keluaran package flag ke stdout — keluaran bawaannya adalah stderr — agar seluruh contoh terlihat pada satu aliran. - Baris 18-21:
flag.Usagediganti fungsi yang mencetak cara pakai laluPrintDefaults, sehingga bantuan-hberformat konsisten. - Baris 22:
flag.PrintDefaultsmencetak daftar flag sebelum parsing dilakukan. - Baris 25:
flag.Parsemembaca argumen command line yang sebenarnya. - Baris 27-28: nilai flag dibaca lewat operator
*pada pointer yang dikembalikan saat deklarasi. - Baris 29-31:
flag.Args()menangkap argumen posisi setelah--dan menggabungkannya menjadi satu baris.
Menjalankan Variasi Program #
Dengan argumen tetap, nilai default tertimpa:
go run flag-demo.go --nama=Budi --umur=25Output yang Dihasilkan:
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
Halo, Budi (umur 25 tahun)
verbose : falseFlag boolean cukup disebut namanya, dan argumen posisi mengikuti tanda --:
go run flag-demo.go --nama=Siti --umur=22 --verbose -- laporan.txt data.csvOutput yang Dihasilkan:
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
Halo, Siti (umur 22 tahun)
verbose : true
posisi : laporan.txt, data.csvPermintaan bantuan berakhir sukses dengan exit code 0:
go run flag-demo.go -hOutput yang Dihasilkan:
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
Cara pakai: go run flag-demo.go [flag] [argumen posisi...]
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstraDaftar flag muncul dua kali karena program memanggil flag.PrintDefaults secara eksplisit, lalu pemrosesan -h memanggil flag.Usage yang mencetak daftar yang sama. Nilai yang salah tipenya dihukum exit status 2:
go run flag-demo.go --umur=tuaOutput yang Dihasilkan:
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
invalid value "tua" for flag -umur: parse error
Cara pakai: go run flag-demo.go [flag] [argumen posisi...]
-nama string
nama pengguna yang disapa (default "tamu")
-umur int
umur pengguna dalam tahun (default 18)
-verbose
tampilkan detail ekstra
exit status 2Baris exit status 2 adalah laporan go run bahwa program berhenti dengan kode 2; go run sendiri lalu keluar dengan kode 1. Binary hasil go build mengembalikan kode 2 secara langsung.
Referensi #
- Dokumentasi package flag
— deklarasi, parsing, dan
FlagSet. - flag.FlagSet — kumpulan flag mandiri untuk subcommand.
- Dokumentasi package os
—
os.Argssebagai sumber argumen mentah.
CLI siap pakai dengan flag biasanya masih butuh struktur lebih kaya — subcommand, berkas konfigurasi, distribusi binary — yang dibahas pada chapter Package flag lanjutan
di section aplikasi command line. Selanjutnya di section ini kita menutup dengan embed, teknik menyematkan berkas statis langsung ke dalam binary.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
flag-demo.go
Unduh berkaspackage main
import (
"flag"
"fmt"
"os"
"strings"
)
func main() {
// flag.String, flag.Int, dan flag.Bool mengembalikan pointer ke nilai.
nama := flag.String("nama", "tamu", "nama pengguna yang disapa")
umur := flag.Int("umur", 18, "umur pengguna dalam tahun")
verbose := flag.Bool("verbose", false, "tampilkan detail ekstra")
// Alihkan keluaran package flag ke stdout, lalu cetak teks usage.
flag.CommandLine.SetOutput(os.Stdout)
flag.Usage = func() {
fmt.Println("Cara pakai: go run flag-demo.go [flag] [argumen posisi...]")
flag.PrintDefaults()
}
flag.PrintDefaults()
// flag.Parse membaca argumen command line sebenarnya.
flag.Parse()
fmt.Printf("Halo, %s (umur %d tahun)\n", *nama, *umur)
fmt.Println("verbose :", *verbose)
if sisa := flag.Args(); len(sisa) > 0 {
fmt.Println("posisi :", strings.Join(sisa, ", "))
}
}