Reflection Temelleri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 83 / 107.
Yansıma (Reflection), bir programın kendi yapısını çalışma zamanında incelemesine ve değiştirmesine olanak tanır. Go'nun reflect paketi bu yeteneği sağlayarak; türleri incelemenize, struct alanlarını okumanıza ve metotları dinamik olarak çağırmanıza imkan tanır.
Yansımadaki (reflection) iki temel tür reflect.Type ve reflect.Value'dur. Bunları reflect.TypeOf() ve reflect.ValueOf() kullanarak elde edersiniz:
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()) // 2Struct alanlarının adlarını, türlerini ve değerlerini incelemek için bu alanlar üzerinde döngü kurabilirsiniz:
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: 30Reflection güçlüdür ancak beraberinde bazı ödünler getirir: derleme zamanı tür denetimini atlar, doğrudan erişimden daha yavaş çalışır ve kodun anlaşılmasını zorlaştırır. JSON marshaling, ORM eşleme veya türün derleme zamanında bilinmediği jenerik yardımcı programlar oluşturma gibi görevler için idareli kullanın.
Görev
KolayHerhangi bir struct'ı incelemek ve yapısını raporlamak için yansıma (reflection) kullanan bir struct denetçisi (inspector) oluşturalım! Bu, yansıma için pratik bir kullanım örneğidir; derleme zamanında bilinmeyen türlerle çalışan yardımcı araçlar oluşturmak.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
inspector.go: Yansıma tabanlı denetleme aracınızı oluşturun.Kendisine iletilen herhangi bir struct'ı incelemek için
reflectpaketini kullanan birInspectStruct(v any) stringfonksiyonu oluşturun. Fonksiyonunuz şunları içeren biçimlendirilmiş bir rapor döndürmelidir:- Struct'ın tür adı
- Struct'ın türü (kind) ("struct" olmalıdır)
- Alan (field) sayısı
- Her alan için: alan adı, türü ve mevcut değeri
Çıktı formatı şu şekilde 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 gezinmek içinNumField(), meta veriler için tür üzerindeField(i)ve gerçek değerler için değer üzerindeField(i)kullanın.main.go: Örnek struct'lar tanımlayın ve denetçinizi kullanın.Bir struct türünü (
productveyaemployee) ve alan değerlerini okuyun, ardından uygun struct'ı oluşturun ve denetleyin.productiçin:Name(string),Price(float64) veInStock(bool) alanlarına sahip birProductstruct'ı oluşturun. Adı, fiyatı ve stok durumunu okuyun.employeeiçin:ID(int),Name(string) veDepartment(string) alanlarına sahip birEmployeestruct'ı oluşturun. ID'yi, adı ve departmanı okuyun.Oluşturulan struct'ı
InspectStructfonksiyonuna gönderin ve sonucu yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Struct türü (
productveyaemployee) - Sonraki satırlar: O struct türü için alan değerleri
Örneğin, şu girdi verildiğinde:
product
Laptop
999.99
trueÇıktınız şu şekilde olmalıdır:
Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): trueVe şu girdi verildiğinde:
employee
42
Alice Johnson
EngineeringÇıktınız şu şekilde olmalıdır:
Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): EngineeringVe şu girdi verildiğinde:
product
Headphones
79.50
falseÇıktınız şu şekilde olmalıdır:
Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): falseDenetçinizin, yapılarını önceden bilmeden farklı struct türleriyle nasıl çalıştığına dikkat edin; yansımanın gücü budur! Aynı InspectStruct fonksiyonu hem Product hem de Employee struct'larını dinamik olarak işler.
Kopya kağıdı
reflect paketi, programların çalışma zamanında kendi yapılarını incelemesine ve değiştirmesine olanak tanır.
İki temel tür, reflect.TypeOf() ve reflect.ValueOf() kullanılarak elde edilen reflect.Type ve reflect.Value'dur:
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 struct alanları üzerinde döngü kurun:
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 (Reflection), derleme zamanı tür denetimini atlar, doğrudan erişimden daha yavaş çalışır ve kodun anlaşılmasını zorlaştırır. JSON marshaling, ORM eşleme veya türün derleme zamanında bilinmediği genel amaçlı araçlar (generic utilities) oluşturma gibi görevler için kullanın.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Name, Price ve InStock alanlarına sahip Product yapısı
type Product struct {
Name string
Price float64
InStock bool
}
// ID, Name ve Department alanlarına sahip Employee yapısı
type Employee struct {
ID int
Name string
Department string
}
func main() {
reader := bufio.NewReader(os.Stdin)
// Yapı (struct) türünü oku
structType, _ := reader.ReadString('\n')
structType = strings.TrimSpace(structType)
if structType == "product" {
// Ürün 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 yapısı oluşturun
// TODO: Ürün ile InspectStruct fonksiyonunu çağırın ve sonucu yazdırın
} else if structType == "employee" {
// Çalışan 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 yapısı oluşturun
// TODO: Çalışan ile InspectStruct fonksiyonunu çağırın ve sonucu yazdırın
}
}
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ış