Reflection Temelleri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 83 / 107.
Yansıma, bir programın çalışma zamanında kendi yapısını incelemesine ve değiştirmesine olanak tanır. Go'nun reflect paketi bu olanağı sağlayarak türleri incelemenize, yapı alanlarını okumanıza ve yöntemleri dinamik olarak çağırmanıza imkân verir.
Yansıtmadaki iki temel tür reflect.Type ve reflect.Value’dur. Bunları reflect.TypeOf() ve reflect.ValueOf() kullanarak elde edersin:
import "reflect"
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
fmt.Println(t.Name()) // Person
fmt.Println(t.Kind()) // struct
fmt.Println(v.NumField()) // 2Adlarını, türlerini ve değerlerini incelemek için yapı alanları üzerinde yineleme yapabilirsiniz:
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
// Çıktı:
// Name: Alice
// Age: 30Yansıma güçlüdür ancak bazı ödünleri beraberinde getirir: derleme zamanındaki tür denetimini devre dışı bırakır, doğrudan erişimden daha yavaş çalışır ve kodun anlaşılmasını zorlaştırır. Yansıma; JSON serileştirme, ORM eşleme veya türün derleme zamanında bilinmediği genel amaçlı yardımcı programlar oluşturma gibi görevlerde idareli kullanılmalıdır.
Görev
KolayYansımayı kullanarak herhangi bir yapıyı inceleyen ve yapısını raporlayan bir yapı denetleyicisi oluşturalım! Bu, yansımanın pratik bir kullanım alanıdır: derleme zamanında türleri bilinmeyen türlerle çalışan yardımcı araçlar oluşturmak.
Kodunuzu iki dosyaya ayıracaksınız:
inspector.go: Yansıma tabanlı inceleme yardımcı programınızı oluşturun.Herhangi bir yapıyı incelemek için
InspectStruct(v any) stringpaketini kullananreflectişlevini oluşturun. İşleviniz aşağıdakileri içeren biçimlendirilmiş bir rapor döndürmelidir:- Yapının tür adı
- Yapının türü ("struct" olmalıdır)
- Alanların sayısı
- Her alan için: alan adı, türü ve mevcut değeri
Çıktı biçimi şöyle olmalıdır:
Type: [TypeName] Kind: struct Fields: [count] - [FieldName] ([FieldType]): [Value] - [FieldName] ([FieldType]): [Value] ...Tür bilgilerini almak için
reflect.TypeOf()ve alan değerlerine erişmek içinreflect.ValueOf()kullanın. Alanlar arasında, meta veriler için tür üzerindeNumField()veField(i), gerçek değerler içinse değer üzerindeField(i)kullanarak yineleyin.main.go: Örnek yapıları tanımlayın ve denetleyicinizi kullanın.Bir yapı türünü (
productveyaemployee) ve alan değerlerini okuyun, ardından uygun yapıyı oluşturup inceleyin.productiçin:Product(string),Name(float64) vePrice(bool) alanlarına sahip birInStockyapısı oluşturun. Adı, fiyatı ve stok durumunu okuyun.employeeiçin:Employee(int),ID(string) veName(string) alanlarına sahip birDepartmentyapısı oluşturun. ID'yi, adı ve departmanı okuyun.Oluşturulan yapıyı
InspectStructişlevine aktarın ve sonucu yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Yapı türü (
productveyaemployee) - Sonraki satırlar: Bu yapı türünün alan değerleri
Örneğin, aşağıdaki girdi verildiğinde:
product
Laptop
999.99
trueÇıktınız şöyle olmalıdır:
Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): trueVe aşağıdaki girdi verildiğinde:
employee
42
Alice Johnson
EngineeringÇıktınız şöyle olmalıdır:
Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): EngineeringVe aşağıdaki girdi verildiğinde:
product
Headphones
79.50
falseÇıktınız şöyle olmalıdır:
Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): falseDenetleyicinizin, yapılarını önceden bilmeden farklı yapı türleriyle nasıl çalıştığına dikkat edin. Yansımanın gücü budur! Aynı InspectStruct işlevi hem Product hem de Employee yapılarını dinamik olarak işler.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Name, Price ve InStock alanlarına sahip Product struct'ı
type Product struct {
Name string
Price float64
InStock bool
}
// ID, Name ve Department alanlarına sahip Employee struct'ı
type Employee struct {
ID int
Name string
Department string
}
func main() {
reader := bufio.NewReader(os.Stdin)
// Struct türünü oku
structType, _ := reader.ReadString('\n')
structType = strings.TrimSpace(structType)
if structType == "product" {
// Product alanlarını oku
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
inStockStr, _ := reader.ReadString('\n')
inStockStr = strings.TrimSpace(inStockStr)
inStock, _ := strconv.ParseBool(inStockStr)
// TODO: Okunan değerlerle bir Product struct'ı oluştur
// TODO: InspectStruct'ı product ile çağır ve sonucu yazdır
} else if structType == "employee" {
// Employee alanlarını oku
idStr, _ := reader.ReadString('\n')
idStr = strings.TrimSpace(idStr)
id, _ := strconv.Atoi(idStr)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
department, _ := reader.ReadString('\n')
department = strings.TrimSpace(department)
// TODO: Okunan değerlerle bir Employee struct'ı oluştur
// TODO: InspectStruct'ı employee ile çağır ve sonucu yazdır
}
}
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 Pool12İleri Düzey OOP Kavramları
Functional Options DeseniGo'da Builder DeseniMetot ZincirlemeTür Takma Adları vs. TanımlamalarReflection TemelleriKod Üretimine Genel BakışKendi başına pratik yap: Online Go derleyicisi