Parameter ...T
Taruh ... sebelum tipe parameter terakhir. Pemanggil lalu bisa mengirim argumen bertipe itu sebanyak apa pun, termasuk tanpa argumen sama sekali. Di dalam fungsi, parameternya berupa slice.
Program ini mencetak 0, 5, dan 10. Tanpa argumen, nums adalah slice nil dengan panjang 0, jadi perulangannya tidak dijalankan.
Parameter biasa boleh ditaruh lebih dulu. Hanya parameter terakhir yang boleh variadic:
func logf(level string, format string, args ...any)
Mengirim slice dengan s...
Kalau kamu sudah punya slice, kamu tidak bisa mengirimnya langsung: sum(nums) gagal dengan cannot use nums (variable of type []int) as int value in argument to sum. Sebarkan dengan ... setelah argumennya:
append juga variadic, dan itulah sebabnya menggabungkan dua slice ditulis append(a, b...).
Spread harus menjadi satu-satunya isi di posisi variadic. sum(1, nums...) gagal dengan too many arguments in call to sum. Bangun slice gabungannya lebih dulu dengan append.
Slice-nya dipakai bersama, bukan disalin
Saat kamu memanggil dengan argumen satuan, Go membuat slice baru untuk argumen-argumen itu. Saat kamu menyebarkan slice yang sudah ada dengan s..., fungsi menerima slice yang sama persis. Menulis ke elemennya mengubah data milik pemanggil.
Output:
[7 8 9]
[0 8 9]
Fungsi variadic yang mengubah parameternya sebaiknya menuliskan hal itu di dokumentasinya, atau menyalin lebih dulu dengan slices.Clone. Sebagian besar fungsi variadic hanya membaca argumennya, jadi masalah ini jarang muncul, tetapi ini perbedaan nyata dari bahasa yang rest parameter-nya selalu berupa array baru.
...any dan cara kerja fmt.Println
fmt.Println dideklarasikan sebagai func Println(a ...any) (n int, err error). any (alias untuk interface{} sejak Go 1.18) menerima semua tipe, jadi kamu bisa mengirim string, angka, dan struct dalam satu panggilan.
Hal pentingnya ada di penerusan: logf meneruskan args... ke Printf. Tanpa titik-titik itu, Printf menerima satu argumen, yaitu []any, dan baris peringatannya tercetak [WARN] [3 8] of %!d(MISSING) workers idle. go vet melaporkan missing ... in args forwarded to printf-like function hanya kalau parameter format diteruskan tanpa diubah, seperti di fmt.Printf(format, args). Di sini format-nya dibangun dengan +, jadi vet diam saja dan titik-titik itu jadi tanggung jawabmu.
[]string tidak bisa disebarkan ke ...any. Tipe elemennya harus sama persis, jadi konversikan lebih dulu:
names := []string{"a", "b"}
args := make([]any, len(names))
for i, n := range names {
args[i] = n
}
fmt.Println(args...)
Mewajibkan minimal satu argumen
Parameter variadic menerima nol argumen. Kalau fungsinya butuh minimal satu, jadikan argumen pertama sebagai parameter biasa:
Sekarang maxOf() menjadi error kompilasi, bukan pemeriksaan saat program berjalan. Fungsi bawaan max sendiri bekerja dengan cara yang sama: ia butuh minimal satu argumen.
Parameter variadic sebagai argumen opsional
Go tidak punya nilai default untuk parameter. Parameter variadic kadang dipakai untuk meniru satu argumen opsional:
func connect(addr string, timeout ...time.Duration)
Cara ini bisa dipakai tetapi kurang enak dibaca, karena pemanggil bisa mengirim tiga timeout dan signature-nya tidak menjelaskan mana yang dipakai. Untuk lebih dari satu opsi, lebih baik pakai struct konfigurasi, atau pola functional options (...Option, dengan setiap Option berupa fungsi yang mengisi sebuah field). Pola itu memang variadic, tetapi setiap argumennya punya arti yang jelas.
Ringkasan aturan
| Aturan | Contoh |
|---|---|
| Hanya parameter terakhir yang boleh variadic | func f(a string, b ...int) |
| Di dalam fungsi, parameternya berupa slice | b bertipe []int |
| Tanpa argumen menghasilkan slice nil | f("x") membuat b == nil |
Sebarkan slice dengan ... | f("x", nums...) |
| Spread memakai backing array yang sama | menulis ke b[i] mengubah nums |
| Spread tidak boleh dicampur dengan nilai tambahan | f("x", 1, nums...) tidak bisa dikompilasi |
Pertanyaan yang sering diajukan
Apa itu fungsi variadic di Go?
Fungsi yang parameter terakhirnya berbentuk ...T, seperti func sum(nums ...int) int. Fungsi ini bisa dipanggil dengan nol argumen atau lebih bertipe T, dan di dalam fungsi parameternya berupa slice []T.
Bagaimana cara mengirim slice ke fungsi variadic di Go?
Tambahkan ... setelah slice-nya: sum(nums...). Slice itu dikirim apa adanya, tanpa disalin, jadi fungsi melihat backing array yang sama. Kamu tidak bisa mencampur spread dengan argumen satuan: sum(1, nums...) tidak bisa dikompilasi.
Apakah Go punya spread operator?
Hanya untuk argumen terakhir di panggilan variadic: f(s...). Tidak ada spread umum untuk membangun array, struct, atau memanggil fungsi non-variadic dengan slice. append(a, b...) adalah aturan yang sama yang diterapkan pada append bawaan.
Apakah fungsi Go bisa punya dua parameter variadic?
Tidak. Hanya parameter terakhir yang boleh variadic, dan hanya ada satu per fungsi. Kirim daftar tambahan sebagai parameter slice biasa.