Dispatch manual dengan switch os.Args[1] pada chapter sebelumnya bekerja untuk tiga perintah, tetapi tugasnya menumpuk seiring CLI tumbuh: setiap perintah butuh teks bantuan sendiri, daftar flag sendiri, pesan galat yang seragam, dan idealnya tab completion untuk shell. Framework CLI menyerap seluruh pekerjaan mekanis tersebut sehingga kita cukup mendefinisikan perintah dan logikanya. Pada chapter ini kita memakai Cobra, framework paling banyak dipakai di ekosistem Go yang menjadi tulang punggung Docker CLI, kubectl, Hugo, dan ribuan alat lain; dokumentasi lengkapnya tersedia di cobra.dev .

Mengapa Memakai Framework #

Cobra menggantikan bagian-bagian boilerplate dispatch manual dengan mekanisme deklaratif:

  • Bantuan otomatis: setiap perintah mendapat flag -h/--help yang mencetak pemakaian, deskripsi, dan daftar flag tanpa satu baris kode tambahan.
  • Struktur perintah bersarang: rootCmd.AddCommand(anakCmd) membentuk pohon perintah, termasuk pesan unknown command yang rapi untuk perintah yang tidak ada.
  • Flag per perintah: setiap subcommand membawa kumpulan flag sendiri dan mewarisi flag milik perintah induk.
  • Completion dan validasi: Cobra menambahkan perintah completion untuk skrip autocomplete shell serta validator argument seperti cobra.ExactArgs(1).

Cobra adalah dependency pihak ketiga, jadi contoh pada chapter ini dibuat sebagai module terpisah di luar bundle halaman. Pembuatan module-nya memakai tiga perintah berikut:

bash
mkdir todo && cd todo
go mod init example.com/todo
go get github.com/spf13/[email protected]

Output yang Dihasilkan:

text
go: creating new go.mod: module example.com/todo
go: added github.com/spf13/cobra v1.10.2
go: added github.com/spf13/pflag v1.0.9

Versi v1.10.2 adalah rilis stabil terbaru yang berhasil diambil saat penulisan chapter ini; cek versi terbaru dengan go list -m -versions github.com/spf13/cobra.

Command, Run, dan AddCommand #

Satu perintah Cobra direpresentasikan struct cobra.Command dengan tiga field paling dasar: Use berisi pola pemakaian, Short berisi deskripsi singkat, dan Run berisi fungsi yang dijalankan ketika perintah dipilih. Program demo todo berikut mendefinisikan perintah induk beserta dua anak, add dan list:

go
var daftar = []string{"belajar Go", "merapikan kode"}

var rootCmd = &cobra.Command{
	Use:   "todo",
	Short: "Aplikasi pengelola tugas contoh",
}

var addCmd = &cobra.Command{
	Use:   "add <nama tugas>",
	Short: "Tambahkan satu tugas baru",
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		prioritas, _ := cmd.Flags().GetString("prioritas")
		daftar = append(daftar, args[0])
		fmt.Printf("ditambahkan: %s (prioritas: %s)\n", args[0], prioritas)
	},
}

var listCmd = &cobra.Command{
	Use:   "list",
	Short: "Tampilkan seluruh tugas",
	Run: func(cmd *cobra.Command, args []string) {
		if len(daftar) == 0 {
			fmt.Println("belum ada tugas")
			return
		}
		for i, t := range daftar {
			fmt.Printf("%d. %s\n", i+1, t)
		}
	},
}

Perhatikan pola Run: func(cmd *cobra.Command, args []string): parameter args hanya berisi argument posisi karena seluruh flag sudah dipisahkan parser. Flag milik subcommand didaftarkan pada fungsi init(), lalu kedua anak menempel pada induk:

go
func init() {
	addCmd.Flags().StringP("prioritas", "p", "rendah", "tingkat prioritas tugas")
	rootCmd.AddCommand(addCmd)
	rootCmd.AddCommand(listCmd)
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}

Execute mengurai os.Args, mencocokkan subcommand pertama, menjalankan Run yang sesuai, dan mengembalikan galat bila perintah tidak dikenal.

Menjalankan CLI Cobra #

Dari direktori module, program dijalankan seperti biasa namun dengan subcommand sebagai argument pertama:

bash
go run . list
go run . add "menulis dokumentasi" --prioritas sedang

Output yang Dihasilkan:

text
1. belajar Go
2. merapikan kode
ditambahkan: menulis dokumentasi (prioritas: sedang)

Kedua baris pertama adalah output list, sedangkan baris ketiga adalah output add yang menangkap flag --prioritas melalui cmd.Flags().GetString("prioritas"). Flag juga tersedia dalam bentuk pendek karena pendaftaran memakai StringP:

bash
go run . add -p tinggi "menulis dokumentasi"

Output yang Dihasilkan:

text
ditambahkan: menulis dokumentasi (prioritas: tinggi)

Bantuan dan Galat yang Dihasilkan Otomatis #

Coba minta bantuan pada perintah induk:

bash
go run . --help

Output yang Dihasilkan:

text
Aplikasi pengelola tugas contoh

Usage:
  todo [command]

Available Commands:
  add         Tambahkan satu tugas baru
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command
  list        Tampilkan seluruh tugas

Flags:
  -h, --help   help for todo

Use "todo [command] --help" for more information about a command.

Seluruh teks tersebut dirakit dari field Use dan Short tanpa kita menulis satu baris pun. Perintah completion dan help ditambahkan Cobra secara otomatis. Bantuan per subcommand juga tersedia, misalnya go run . add --help:

text
Tambahkan satu tugas baru

Usage:
  todo add <nama tugas> [flags]

Flags:
  -h, --help               help for add
  -p, --prioritas string   tingkat prioritas tugas (default "rendah")

Validasi argument bekerja lewat field Args: cobra.ExactArgs(1) pada addCmd. Pemanggilan tanpa argument ditolak dengan pesan galat dan exit code 1:

bash
go run . add

Output yang Dihasilkan:

text
Error: accepts 1 arg(s), received 0
Usage:
  todo add <nama tugas> [flags]

Flags:
  -h, --help               help for add
  -p, --prioritas string   tingkat prioritas tugas (default "rendah")

exit status 1

Perintah yang tidak dikenal juga dibalas rapi oleh framework:

bash
go run . hapus

Output yang Dihasilkan:

text
Error: unknown command "hapus" for "todo"
Run 'todo --help' for usage.
exit status 1

Baris exit status 1 berasal dari go run karena program keluar dengan kode 1 setelah mencetak galat.

Kode pada chapter ini sengaja tidak disertakan sebagai berkas di bundle halaman karena membutuhkan dependency eksternal. Bila jumlah perintah masih sedikit dan kita ingin tetap hanya memakai standard library, pola dispatch manual pada chapter Subcommand adalah alternatif yang sah.

Referensi #