Semua fungsi yang kita tulis sejauh ini menerima jumlah argumen yang terpas mati: fungsi dua parameter selalu dipanggil dengan tepat dua argumen. Kenyataannya banyak operasi alami berbentuk bebas — menjumlahkan sekumpulan angka, menggabungkan sekumpulan kata, mencatat log dengan berbagai data tambahan. Go mengatasinya tanpa kelebihan sintaks: satu parameter khusus bernama parameter variadic yang siap menerima nol, satu, atau banyak argumen. Pada chapter ini kita akan memakai parameter tersebut, mengirim slice yang sudah ada, lalu membandingkannya dengan parameter slice biasa.

Parameter Variadic #

Tanda variadic adalah tiga titik sebelum tipe parameter terakhir: angka ...int. Di dalam badan fungsi, angka bukan deretan nilai terpisah, melainkan slice bertipe []int yang berisi seluruh argumen — lengkap dengan kemampuan len, pengindeksan, dan range:

go
// jumlah menjumlahkan sejumlah bilangan, berapa pun jumlahnya.
func jumlah(angka ...int) int {
	total := 0
	for _, v := range angka {
		total += v
	}
	return total
}

Pemanggilan bebas menentukan jumlahnya: jumlah(5) mengirim satu argumen, jumlah(5, 10, 15) mengirim tiga, dan jumlah() sah sepenuhnya — slice angka berisi nol elemen sehingga fungsi mengembalikan 0. Kita tidak perlu membuat slice secara manual; kompiler merangkai argumen-argumen menjadi slice untuk kita.

Mengirim Slice dengan Tanda … #

Sering kali data sudah berbentuk slice sebelum pemanggilan. Tanda ... yang sama dipakai lagi di sisi pemanggil untuk membuka (spread) isi slice menjadi deretan argumen: jumlah(data...) dengan data := []int{2, 4, 6} sama nilainya dengan menulis jumlah(2, 4, 6). Pola dua sisi ini — ...int di deklarasi dan data... di pemanggilan — adalah pasangan resmi yang dibaca sebagai “kumpulan masuk, kumpulan keluar”.

Variadic Selalu di Posisi Terakhir #

Satu fungsi hanya boleh punya satu parameter variadic dan wajib menempatkan parameter tersebut paling akhir. Parameter reguler boleh mendahuluinya, seperti awalan string pada fungsi rangkai berikut:

go
// rangkai menggabungkan awalan dan sejumlah kata.
func rangkai(awalan string, kata ...string) string {
	hasil := awalan
	for _, k := range kata {
		hasil += " " + k
	}
	return hasil
}

Aturan posisi ini menjaga pemanggilan tetap tak ambigu: rangkai("Go:", "belajar", "fungsi") mengikat "Go:" ke awalan dan sisanya ke kata. Deklarasi func rangkai(kata ...string, awalan string) tidak lolos kompilasi karena kompiler tidak tahu di mana batas kedua parameter.

Parameter Variadic versus Parameter Slice #

Kedua bentuk terlihat mirip karena keduanya berujung pada []int di dalam fungsi, tetapi kontrak pemanggilannya berbeda. Tabel berikut memetakan perbedaan yang menentukan pilihan kita:

AspekParameter angka ...intParameter angka []int
Pemanggilan bebasjumlah(5, 10) sahWajib slice: jumlah([]int{5, 10})
Pemakaian slice yang adajumlah(data...)jumlah(data)
Pemanggilan kosongjumlah() mengirim slice kosongHarus mengirim nil atau []int{}
Kontrak APIJumlah argumen fleksibelPemanggil mengelola koleksi

Pilih parameter variadic ketika fleksibilitas jumlah argumen memang bagian dari kontrak fungsi — contohnya fmt.Println(a ...any). Pilih parameter slice ketika data memang selalu berbentuk koleksi yang dikelola pemanggil, misalnya fungsi pemroses baris tabel.

Program Utuh #

Berkas variadic-demo.go menjalankan fungsi jumlah dengan tiga jumlah argumen berbeda, memakai spread data..., lalu memanggil rangkai dengan parameter tetap di depan. Jalankan dari direktori chapter:

bash
go run variadic-demo.go

Output yang Dihasilkan:

text
jumlah()              = 0
jumlah(5)             = 5
jumlah(5, 10, 15)     = 30
jumlah(data...)       = 12
rangkai("Go:", kata...) = Go: belajar fungsi variadic

Mari kita telaah baris demi baris program di atas:

  1. Baris 6 (func jumlah(angka ...int) int): mendeklarasikan parameter variadic angka yang diperlakukan sebagai []int di dalam fungsi.
  2. Baris 8 (for _, v := range angka): menjelajahi seluruh argumen yang dikumpulkan menjadi slice, lalu menambahkannya ke total.
  3. Baris 15 (func rangkai(awalan string, kata ...string)): menempatkan parameter variadic di posisi terakhir setelah parameter reguler awalan.
  4. Baris 18 (hasil += " " + k): merangkai setiap kata dari slice kata ke belakang awalan dengan pemisah spasi.
  5. Baris 23–33 (isi main): memanggil jumlah dengan nol, satu, dan tiga argumen, lalu memakai bentuk data... dan kata... untuk mengirim slice yang sudah ada.

Fleksibilitas variadic menyempurnakan kotak perkakas fungsi kita, tetapi Go masih menyimpan satu kejutan besar: fungsi bukan sekadar blok kode yang dipanggil — fungsi adalah nilai yang bisa disimpan, dikirim, dan dikembalikan. Chapter First-Class Function membuka pintu tersebut.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

variadic-demo.go

Unduh berkas
go
package main

import "fmt"

// jumlah menjumlahkan sejumlah bilangan, berapa pun jumlahnya.
func jumlah(angka ...int) int {
	total := 0
	for _, v := range angka {
		total += v
	}
	return total
}

// rangkai menggabungkan awalan dan sejumlah kata.
func rangkai(awalan string, kata ...string) string {
	hasil := awalan
	for _, k := range kata {
		hasil += " " + k
	}
	return hasil
}

func main() {
	fmt.Println("jumlah()              =", jumlah())
	fmt.Println("jumlah(5)             =", jumlah(5))
	fmt.Println("jumlah(5, 10, 15)     =", jumlah(5, 10, 15))

	data := []int{2, 4, 6}
	fmt.Println("jumlah(data...)       =", jumlah(data...))

	kata := []string{"belajar", "fungsi", "variadic"}
	fmt.Println("rangkai(\"Go:\", kata...) =", rangkai("Go:", kata...))
}