Cara Membuat Command-Line Flags Custom di Golang

tech · 19 Jun 2023 · ~3 menit
Photo by @joshuafuller on Unsplash
Photo by @joshuafuller on Unsplash

Pengenalan

Jika kalian familiar dengan command-line interface, kalian mungkin pernah melihat flag atau penanda seperti -h, -v, --name foo, dan sebagainya. Beberapa flag menggunakan tipe data primitif seperti string, int, bool, dan sejenisnya. Sisanya adalah flag khusus yang menggunakan pola spesifik atau struktur data seperti IP, URL, Array, Map, dan sebagainya. Golang menyediakan sebuah library bawaan flag untuk membuat flag command-line khusus. Beberapa fungsi yang disediakan untuk membuat flag sudah cukup jelas, seperti flag.String, flag.Int, dsb. Tapi, bagaimana dengan custom flag? Di artikel ini, kalian akan mempelajari beberapa cara untuk membuat flag command-line custom pada Golang.

Contoh

Misalnya kalian mau membuat flag custom yang menerima sebuah list berisi string. Penggunaan flag-nya akan seperti ini:

1
2
$ go run main.go --list a --list b,c,d
[a b c d]

Di bawah ini adalah beberapa cara untuk mendefinisikan flag custom tersebut.

Flag Var

flag.Var adalah cara mendefinisikan flag custom. flag.Var menerima sebuah custom struct yang mengimplementasikan interface flag.Value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
type ListFlag []string

func (f *ListFlag) String() string {
	b, _ := json.Marshal(*f)
	return string(b)
}

func (f *ListFlag) Set(value string) error {
	for _, str := range strings.Split(value, ",") {
		*f = append(*f, str)
	}
	return nil
}

func main() {
    // foo and bar as a default value
	list := ListFlag([]string{"foo", "bar"})
	flag.Var(&list, "list", "your flag usage")

	flag.Parse()
	fmt.Println(list) // [foo bar a b c d]
}

Hal penting yang perlu diperhatikan adalah metode Set. Setiap flag kalian dipanggil, metode Set akan dipanggil.

Flag Func

flag.Func adalah cara yang mudah untuk mendefinisikan sebuah flag custom. flag.Func menggunakan flag.Var sebagai basisnya, jadi kalian tidak perlu membuat custom struct.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main() {
	list := ListFlag([]string{"foo", "bar"})
	flag.Func("list", "your flag usage", func(s string) error {
		for _, str := range strings.Split(s, ",") {
			list = append(list, str)
		}
		return nil
	})

	flag.Parse()
	fmt.Println(list) // [foo bar a b c d]
}

Seperti kalian lihat, parameter terakhir dari flag.Func adalah metode Set yang kalian implementasikan pada contoh sebelumnya.

Flag TextVar

flag.TextVar adalah cara baru yang diperkenalkan pada go1.19. flag.TextVar menggunakan flag.Var sebagai basisnya seperti flag.Func, tapi menerima interface encoding.TextUnmarshaler dan encoding.TextMarshaler, dan bukan flag.Value. Artinya, kalian dapat menggunakan struct bawaan seperti big.Int, netip.Addr, dan time.Time sebagai flag tanpa harus mengimplementasikan custom struct.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
type ListFlag []string

func (f *ListFlag) MarshalText() ([]byte, error) {
	return json.Marshal(*f)
}

func (f *ListFlag) UnmarshalText(b []byte) error {
	for _, str := range strings.Split(string(b), ",") {
		*f = append(*f, str)
	}
	return nil
}

func main() {
	list := ListFlag([]string{"foo", "bar"})
	flag.TextVar(&list, "list", &list, "your flag usage")

	flag.Parse()
	fmt.Println(list)
}

Seperti yang kalian lihat, ini mirip dengan flag.Var, tapi menggunakan MarshalText dan UnmarshalText, sebagai pengganti metode String dan Set.

Kesimpulan

Sekarang kalian tahu beberapa cara mendefinisikan command-line flag custom menggunakan Golang. Jika ingin mempelajari package flag lebih lanjut, kalian bisa membaca dokumentasi resminya di sini.

Terima kasih sudah membaca!

· · ·

Suka Konten Ini?

Bentuk dukungan apapun saya hargai! Dukung saya melalui Bitcoin, Ko-fi, Trakteer, atau lanjut baca konten saya yang lainnya. Kamu bisa menulis respon lewat Webmention dan beritahu saya URLnya lewat Telegraph.

Tulis komentar anda di bawah