ProgramlamaFullstack Geliştirici

Go dilinde anonim fonksiyonlar nasıl uygulanır ve kullanılır, ayrıca bu fonksiyonların parametre olarak kullanılmasının özelikleri nelerdir?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Sorunun Tarihi

Go'da anonim fonksiyonlar (function literals, closures) fonksiyonel stili, geri çağırmaları ve algoritmaların sade bir şekilde kapsüllenmesini desteklemek için ortaya çıkmıştır. Genellikle koleksiyonların işlenmesi, asenkron görevler için ve parametre olarak iletilmek üzere kullanılır.

Problem

Anonim fonksiyonlar olmadan kod gereksiz hale gelir: Her bir işleme ayrı bir isimlendirilmiş fonksiyona taşınmak zorundadır. Ancak, bu kullanımda bazı sorular ortaya çıkar: "değişkenlerin yakalanması" nasıl çalışır, bellek nerede saklanır, argüman olarak bildirimde ve geçişte hangi detaylar vardır? Dışarıdan değiştirildiğinde değişkenlerin yakalanması korunuyor mu? En yaygın hata, döngüdeki değişkenin yanlış şekilde yakalanmasıdır.

Çözüm

Anonim fonksiyonlar, literal olarak tanımlanır ve değişkenlere atanabilir veya doğrudan kullanılabilir. Eğer anonim bir fonksiyon dış alanın değişkenlerine erişiyorsa, bu değişkenler "yakalanır" ve closure'ın yaşam süresi için saklanır. Fonksiyon parametresi olarak, anonim fonksiyon genellikle fonksiyonun imzası ile uyumlu bir func tipi ile geçirilir. En büyük problemler döngü değişkenlerinin yakalanması sırasında oluşur — burada, eğer mantığı bir closure içine sarmak gerekiyorsa, mutlaka döngü içinde yeni bir değişken oluşturmalısınız.

Kod örneği:

func operate(nums []int, op func(int) int) []int { res := make([]int, len(nums)) for i, n := range nums { res[i] = op(n) } return res } func main() { arr := []int{1, 2, 3} out := operate(arr, func(x int) int {return x * x}) fmt.Println(out) // [1 4 9] }

Anahtar özellikler:

  • Go'daki herhangi bir func literal, dış alandan değişkenler yakalayabilir
  • Closure, ona bir referans olduğu veya kullanıldığı sürece "hayatta kalır", çıkış yapıldıktan sonra bile
  • Anonim bir fonksiyonu parametre olarak geçmek, basitçe func tipi ile yapılır

Yanıltıcı Sorular.

Bir döngüde değişkenin değişken değerinin yakalanması durumunda ne olur?

Tüm closure'lar aynı değişkeni yakalayacak ve döngü sonrası fonksiyon çağrısı yaptığınızda aynı değeri alacaksınız.

Kod örneği:

func main() { a := []func(){} for i := 0; i < 3; i++ { a = append(a, func() { fmt.Println(i) }) } for _, f := range a { f() } // 3 3 3 }

Bunu önlemek için döngü gövdesinde yeni bir değişken oluşturmalısınız:

for i := 0; i < 3; i++ { j := i a = append(a, func() { fmt.Println(j) }) // 0 1 2 }

Anonim fonksiyonlar interface{} türü değerleri olarak kullanılabilir mi?

Fonksiyonlar yalnızca interface{} ile uyumludur, diğer arayüzlerle değil, birbirleriyle karşılaştırılamazlar (nil dışında). Eğer bir closure'ı interface{} olarak geçirirseniz, sadece fonksiyon imzasına tür dönüşümü ile çağırabilirsiniz.

Anonim fonksiyonlar özyinelemeli olabilir mi?

Evet, ancak öncelikle closure için bir isim değişkeni tanımlanmalı ve ardından fonksiyon ona atanmalıdır.

Kod örneği:

var fib func(n int) int fib = func(n int) int { if n < 2 { return n } return fib(n-1) + fib(n-2) } fmt.Println(fib(10)) // 55

Tipik Hatalar ve Antipatronlar

  • Döngü değişkeninin yakalanması sırasında ek bir yerel değişken kullanılmaması
  • Gereksiz yere büyük heap yakalanmış nesnelerle closure'ı geçiş
  • Anonim fonksiyonların, eğer kod okunabilirliği ve tekrar kullanılabilirliği isteniyorsa, bağlam dışında kullanılması

Hayattan Bir Örnek

Olumsuz Durum

Geri çağırmaların listesi üzerinde döngüde geliştirici, işleyiciyi döngü değişkeni ile bir closure olarak bağlar. Tüm geri çağırmalar uyumsuz bir değerle çalışır ve hatalara yol açar.

Artılar:

  • Minimum şablon kodu

Eksiler:

  • Döngüden alınan değerle yaygın bir hata, zor tespit edilen bir hata

Olumlu Durum

Her bir closure için döngü içinde yeni bir değişken oluşturulur, değerlerin doğru yakalandığından ve beklenen davranışın sağlandığından emin olunur.

Artılar:

  • Önerilere basit bir şekilde uymak hataları önlemeye yardımcı olur
  • Kod sade ve güvenlidir

Eksiler:

  • Kapsama ve değişkenlik ile ilgili ince detayları bilmek gerekir