Struct Gömme Temelleri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 35 / 107.
Struct embedding, bir struct türünü diğerinin içine dahil etmek için Go'nun sunduğu mekanizmadır. Bir alan adı kullanmak yerine, sadece türü belirtirsiniz ve Go, gömülü struct'ın alanlarını dıştaki struct'a yükseltir.
İşte temel sözdizimi:
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // gömülü - alan adı yok
}
Address yapısını Person içine gömdüğünüzde, gömülü alanlara doğrudan dış yapı (struct) üzerinden erişebilirsiniz:
func main() {
p := Person{
Name: "Alice",
Address: Address{
City: "London",
Country: "UK",
},
}
fmt.Println(p.City) // London - doğrudan erişim
fmt.Println(p.Country) // UK - doğrudan erişim
fmt.Println(p.Address.City) // bu da çalışır
}
p.City'nin p.Address.City'yi açıkça yazmadan nasıl çalıştığına dikkat edin. Go, gömülü struct'ın alanlarını otomatik olarak yükselterek, onları sanki dış struct'a aitmiş gibi erişilebilir kılar. Gerektiğinde onlara hala gömülü tip adı üzerinden erişebilirsiniz.
Bu, iç alanlara erişmek için her zaman alan adını kullanmanız gereken normal iç içe geçmiş struct'lardan farklıdır. Embedding, ilgili verilerin mantıksal gruplandırmasını korurken daha düz ve daha kullanışlı bir API oluşturur.
Görev
KolayTemiz ve düzenli bir veri modeli oluşturmak için struct gömme (struct embedding) özelliğini kullanan bir araç kayıt sistemi oluşturalım. İletişim bilgilerini araç detaylarından ayırırken, gömme özelliği sayesinde tüm alanlara doğrudan erişim sağlayacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
vehicle.go: Gömme yoluyla birlikte çalışan iki struct oluşturun:OwnerNamevePhonealanlarına (her ikisi de string) sahip birContactInfostruct'ıContactInfo'yu (bir alan adı olmadan) gömen ve kendiMake,ModelveYearalanlarını ekleyen birVehiclestruct'ı
Vehicleüzerinde, tüm araç ve iletişim bilgilerini içeren formatlanmış bir string döndürenSummaryadlı bir metot oluşturun.main.go: Girdiden araç ve sahip detaylarını okuyun, gömülüContactInfoile birVehicleörneği oluşturun ve gömülü alanlara hem doğrudan hem de gömülü tip adı üzerinden erişimi gösterin. Sonunda araç özetini yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Sahip adı (Owner name)
- Satır 2: Telefon numarası (Phone number)
- Satır 3: Araç markası (Vehicle make)
- Satır 4: Araç modeli (Vehicle model)
- Satır 5: Yıl (Year - tam sayı)
Summary metodunuz şu formatta bir string döndürmelidir:
[Year] [Make] [Model] - Owner: [OwnerName], Phone: [Phone]Ana dosyanızda, şunları yazdırarak alan tanıtımını (field promotion) gösterin:
- Doğrudan Vehicle üzerinden erişilen sahip adı (örneğin,
v.OwnerName) - Gömülü tip üzerinden erişilen telefon (örneğin,
v.ContactInfo.Phone) Summarymetodunuzdan gelen tam özet
Örneğin, Alice Smith, 555-1234, Toyota, Camry ve 2023 verildiğinde, çıktınız şöyle olmalıdır:
Alice Smith
555-1234
2023 Toyota Camry - Owner: Alice Smith, Phone: 555-1234Her iki erişim modelinin de (alan tanıtımı yoluyla doğrudan erişim ve gömülü tip adı yoluyla açık erişim) nasıl çalıştığına dikkat edin; bu, gömülü verilerle çalışma konusunda size esneklik sağlar.
Kopya kağıdı
Struct gömme (struct embedding), bir struct türünü bir alan adı belirtmeden başka bir struct içine dahil etmenize olanak tanır. Gömülü struct'ın alanları dıştaki struct'a yükseltilir (promoted), bu da onlara doğrudan erişilebilir olmalarını sağlar.
Temel Sözdizimi
type Address struct {
City string
Country string
}
type Person struct {
Name string
Address // embedded - no field name
}
Gömülü Alanlara Erişme
Gömülü alanlara iki şekilde erişebilirsiniz:
p := Person{
Name: "Alice",
Address: Address{
City: "London",
Country: "UK",
},
}
// Direct access (field promotion)
fmt.Println(p.City) // London
// Through embedded type name
fmt.Println(p.Address.City) // London
Go, gömülü struct'ın alanlarını otomatik olarak yükseltir ve sanki dıştaki struct'a aitmiş gibi doğrudan erişime izin verir. Gerektiğinde onlara gömülü tür adı üzerinden de erişmeye devam edebilirsiniz.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Sahibin adını oku
ownerName, _ := reader.ReadString('\n')
ownerName = strings.TrimSpace(ownerName)
// Telefon numarasını oku
phone, _ := reader.ReadString('\n')
phone = strings.TrimSpace(phone)
// Araç markasını oku
make, _ := reader.ReadString('\n')
make = strings.TrimSpace(make)
// Araç modelini oku
model, _ := reader.ReadString('\n')
model = strings.TrimSpace(model)
// Yılı oku
yearStr, _ := reader.ReadString('\n')
yearStr = strings.TrimSpace(yearStr)
year, _ := strconv.Atoi(yearStr)
// TODO: Gömülü ContactInfo ile bir Vehicle örneği oluşturun
// Yukarıdaki girdiden okunan değerleri kullanın
// TODO: Doğrudan Vehicle üzerinden erişilen sahip adını yazdırın (field promotion)
// Example: fmt.Println(v.OwnerName)
// TODO: Gömülü tür adı üzerinden erişilen telefonu yazdırın
// Example: fmt.Println(v.ContactInfo.Phone)
// TODO: Summary metodunu kullanarak tam özeti yazdırın
// Example: fmt.Println(v.Summary())
// Çözümü uyguladığınızda bu satırları kaldırın
_ = ownerName
_ = phone
_ = make
_ = model
_ = year
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker Pool