ProgramlamaBackend Geliştirici

Go'da yapıların yerleştirilmesi (embedding structs) nasıl çalışır? Yerleştirmenin, yapının içinde normal bir dahil edilmeden farkı nedir? Hangi inceliklere dikkat edilmelidir?

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

Cevap

Go'da embedding (yerleştirme) mekanizması, bir yapıyı başka bir yapıya yerleştirerek, açık bir miras alma kullanmadan yapının davranışını "miras almak" için bir mekanizmadır. Yerleştirilen yapı, yeni yapının alanları olarak (anomim alanlar) tanımlanır.

Bu durumda, yerleştirilen yapının tüm metodları yeni yapının metodları haline gelir, sanki "miras alınmış" gibidir.

Örnek:

package main import "fmt" type Animal struct { Name string } func (a Animal) Speak() { fmt.Println("Benim adım", a.Name) } type Dog struct { Animal // yerleştirme, anomim alan Breed string } func main() { d := Dog{ Animal: Animal{Name: "Rex"}, Breed: "Shepherd", } d.Speak() // Miras alınmış yöntem! fmt.Println(d.Name) // Alan doğrudan erişilebilir }

Yerleştirme ile bir yapının normal bir alana dahil edilmesi arasındaki ana fark:

  • Yerleştirme ile yöntemler ve alanlar yeni yapıda doğrudan erişilebilir,
  • Normal dahil etme durumunda bunlara alan adıyla erişmek gerekir.

Soruya tuzak

"Eğer yerleştirilen yapı ve dış yapı aynı isimde alanlara sahipse, hangisi kullanılacak ve onlara nasıl erişilecektir?"

Birçok kişi yalnızca "üstteki" alanın kullanılacağını düşünmektedir, ancak bu farklı çalışır:

  • Eğer isimler aynıysa, dış alan kullanılacak ve iç alana yerleştirilen yapının adıyla erişilebilir.

Örnek:

type Base struct { Name string } type Child struct { Base // yerleştirme Name string // örtüşen alan } c := Child{Base: Base{Name: "Base"}, Name: "Child"} fmt.Println(c.Name) // Child fmt.Println(c.Base.Name) // Base

Bu konuyla ilgili bilgiyoksulluğundan kaynaklanan gerçek hata örnekleri


Hikaye

Projede bir loglama yapısını yerleştirdik, ardından çocuk tipte Logger alanını tanımladık. Sonuç olarak, d.Logger.Info() çağrıları beklendiği gibi çalışmadı, çünkü yerleştirilen alanlara erişim "benzer isimler" arasında kayboluyordu.


Hikaye

Geliştirici, çocuk yapısında bir yöntemi yeniden tanımlamaya çalıştı, ancak yöntemler "override edilmez" — sadece yeni bir yöntem ortaya çıkar ve ebeveyn yöntemi hala Child.Base.Method() olarak erişilebilir durumda kalır. Bu, bazı kodların "eski" yöntem versiyonunu kullanmasına ve farklı bir mantık beklemesine neden oluyordu.


Hikaye

Yerleştirilmiş yapılarla JSON serileştirimi sırasında beklenmedik durumlar meydana geldi: "yerleştirilen" yapının alanları kök objede yer aldı. Yerleştirmenin marshaling etkisini bilmemek nedeniyle yapı yanlış bir şekilde serileştirildi ve API'nin geriye dönük uyumluluğunu bozdu.