Menu

Golang Variadic Fonksiyonlar: ...T Parametreleri ve s... ile Açma

Variadic bir Go fonksiyonu, tek bir tipten istediğiniz sayıda sondaki argümanı kabul eder. ...T söz dizimini, bir slice'ı s... ile aktarmayı, paylaşım tuzağını ve fmt.Println'in ...any'yi nasıl kullandığını öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

...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 olabilirfunc f(a string, b ...int)
İçeride parametre bir slice'tırb'nin tipi []int
Sıfır argüman nil bir slice verirf("x"), b == nil yapar
Bir slice'ı ... ile açınf("x", nums...)
Açma arka diziyi paylaşırb[i]'ye yazmak nums'ı değiştirir
Açma ile ek değerler karıştırılamazf("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.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA