...T parametresi
Son parametrenin tipinden önce ... koyun. Çağıranlar o zaman o tipten, hiç olmaması dahil, istediği sayıda argüman aktarabilir. Fonksiyonun içinde parametre bir slice'tır.
Bu 0, 5 ve 10 yazdırır. Argüman olmadığında nums uzunluğu 0 olan nil bir slice'tır, bu yüzden döngü hiç çalışmaz.
Normal parametreler önce gelebilir. Yalnızca sonuncusu variadic olabilir:
func logf(level string, format string, args ...any)
Bir slice'ı s... ile aktarmak
Elinizde zaten bir slice varsa onu doğrudan aktaramazsınız: sum(nums), cannot use nums (variable of type []int) as int value in argument to sum hatasıyla başarısız olur. Argümandan sonra ... ile açın:
append da variadic'tir; iki slice'ı birleştirmenin append(a, b...) olmasının nedeni budur.
Açma, variadic konumdaki tek şey olmalıdır. sum(1, nums...), too many arguments in call to sum hatasıyla başarısız olur. Birleşik slice'ı önce append ile oluşturun.
Slice paylaşılır, kopyalanmaz
Tek tek argümanlarla çağırdığınızda Go onlar için yeni bir slice oluşturur. Var olan bir slice'ı s... ile açtığınızda fonksiyon o slice'ın kendisini alır. Elemanlarına yazmak çağıranın verisini değiştirir.
Çıktı:
[7 8 9]
[0 8 9]
Parametresini değiştiren variadic bir fonksiyon bunu belgelemeli ya da önce slices.Clone ile kopyalamalıdır. Çoğu variadic fonksiyon argümanlarını yalnızca okur, bu yüzden bu nadiren sorun çıkarır, ama rest parametrelerinin her zaman yeni bir dizi olduğu dillerden gerçek bir farktır.
...any ve fmt.Println nasıl çalışır
fmt.Println, func Println(a ...any) (n int, err error) olarak tanımlanmıştır. any (Go 1.18'den beri interface{} için bir takma ad) her tipi kabul eder, bu yüzden string'leri, sayıları ve struct'ları tek bir çağrıda aktarabilirsiniz.
Önemli ayrıntı iletmedir: logf, args...'ı Printf'e aktarır. Noktalar olmadan Printf tek bir argüman, bir []any, alır ve uyarı satırı [WARN] [3 8] of %!d(MISSING) workers idle yazdırır. go vet, missing ... in args forwarded to printf-like function uyarısını yalnızca format parametresi fmt.Printf(format, args) örneğindeki gibi değiştirilmeden aktarıldığında raporlar. Burada format + ile oluşturuluyor, bu yüzden vet sessiz kalır ve noktalar size kalır.
Bir []string, ...any içine açılamaz. Eleman tipleri tam olarak eşleşmelidir, bu yüzden önce dönüştürün:
names := []string{"a", "b"}
args := make([]any, len(names))
for i, n := range names {
args[i] = n
}
fmt.Println(args...)
En az bir argüman istemek
Variadic bir parametre sıfır argüman kabul eder. Fonksiyonun en az bir argümana ihtiyacı varsa ilkini normal bir parametre yapın:
Artık maxOf() çalışma zamanı kontrolü yerine bir derleme hatasıdır. Yerleşik max da aynı şekilde çalışır: en az bir argüman ister.
İsteğe bağlı argümanlar olarak variadic parametreler
Go'da varsayılan parametre değerleri yoktur. Variadic bir parametre bazen isteğe bağlı tek bir argümanı taklit etmek için kullanılır:
func connect(addr string, timeout ...time.Duration)
Bu çalışır ama kötü okunur, çünkü çağıranlar üç timeout aktarabilir ve imza hangisinin kazandığını söylemez. Birden fazla seçenek için bir yapılandırma struct'ını ya da functional options kalıbını (...Option, her Option bir alanı ayarlayan bir fonksiyondur) tercih edin. Bu kalıp da variadic'tir, ama her argümanın net bir anlamı vardır.
Kurallar Özeti
| Kural | Örnek |
|---|---|
| Yalnızca son parametre variadic olabilir | func f(a string, b ...int) |
| İçeride parametre bir slice'tır | b'nin tipi []int |
| Sıfır argüman nil bir slice verir | f("x"), b == nil yapar |
Bir slice'ı ... ile açın | f("x", nums...) |
| Açma arka diziyi paylaşır | b[i]'ye yazmak nums'ı değiştirir |
| Açma ile ek değerler karıştırılamaz | f("x", 1, nums...) derlenmez |
Sıkça Sorulan Sorular
Go'da variadic fonksiyon nedir?
Son parametresi func sum(nums ...int) int örneğindeki gibi ...T biçiminde olan bir fonksiyondur. T tipinde sıfır ya da daha fazla argümanla çağrılabilir ve fonksiyonun içinde parametre bir []T slice'ıdır.
Go'da variadic bir fonksiyona slice nasıl aktarılır?
Slice'tan sonra ... ekleyin: sum(nums...). Slice kopyalanmadan olduğu gibi aktarılır, bu yüzden fonksiyon aynı arka diziyi görür. Açma ile tek tek argümanları karıştıramazsınız: sum(1, nums...) derlenmez.
Go'da spread operatörü var mı?
Yalnızca variadic bir çağrının son argümanı için: f(s...). Dizi ya da struct oluşturmak veya variadic olmayan fonksiyonları bir slice ile çağırmak için genel bir spread yoktur. append(a, b...), aynı kuralın yerleşik append'e uygulanmış halidir.
Bir Go fonksiyonunun iki variadic parametresi olabilir mi?
Hayır. Yalnızca son parametre variadic olabilir ve her fonksiyonda bir tane olabilir. Ek listeleri sıradan slice parametreleri olarak aktarın.