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 *:

go
nama := flag.String("nama", "tamu", "nama pengguna yang disapa")

Pola alternatif tanpa pointer mengisi variabel yang sudah Anda deklarasikan sendiri:

go
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 penggunaTanggapan package flagExit code
-h atau --helpteks usage dicetak0
nilai tidak sesuai tipegalat + teks usage2
flag tidak dideklarasikangalat + teks usage2

flag vs os.Args Manual #

Aspekos.Args manualpackage flag
Penguraian --nama=nilaiditulis sendiriotomatis
Nilai defaultditulis sendiribagian deklarasi
Teks bantuanditulis sendiridibangkitkan dari usage text
Argumen posisipenggalan manualflag.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:

go
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:

bash
go run flag-demo.go

Output yang Dihasilkan:

text
  -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 : false

Mari kita telaah baris demi baris program di atas:

  1. Baris 12-14: tiga flag dideklarasikan dengan nilai default dan teks usage; masing-masing mengembalikan pointer.
  2. Baris 17: flag.CommandLine.SetOutput(os.Stdout) mengalihkan keluaran package flag ke stdout — keluaran bawaannya adalah stderr — agar seluruh contoh terlihat pada satu aliran.
  3. Baris 18-21: flag.Usage diganti fungsi yang mencetak cara pakai lalu PrintDefaults, sehingga bantuan -h berformat konsisten.
  4. Baris 22: flag.PrintDefaults mencetak daftar flag sebelum parsing dilakukan.
  5. Baris 25: flag.Parse membaca argumen command line yang sebenarnya.
  6. Baris 27-28: nilai flag dibaca lewat operator * pada pointer yang dikembalikan saat deklarasi.
  7. Baris 29-31: flag.Args() menangkap argumen posisi setelah -- dan menggabungkannya menjadi satu baris.

Menjalankan Variasi Program #

Dengan argumen tetap, nilai default tertimpa:

bash
go run flag-demo.go --nama=Budi --umur=25

Output yang Dihasilkan:

text
  -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 : false

Flag boolean cukup disebut namanya, dan argumen posisi mengikuti tanda --:

bash
go run flag-demo.go --nama=Siti --umur=22 --verbose -- laporan.txt data.csv

Output yang Dihasilkan:

text
  -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.csv

Permintaan bantuan berakhir sukses dengan exit code 0:

bash
go run flag-demo.go -h

Output yang Dihasilkan:

text
  -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 ekstra

Daftar 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:

bash
go run flag-demo.go --umur=tua

Output yang Dihasilkan:

text
  -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 2

Baris 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 #

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 berkas
go
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, ", "))
	}
}