Struct İşaretçileri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 20 / 107.
Struct'larla çalışırken, büyük veri yapılarını kopyalamaktan kaçınmak ve orijinal struct'ı değiştirmek için genellikle pointer'lar kullanırsınız. Bir struct pointer'ı, o struct örneğinin bellek adresini tutar.
Mevcut bir struct üzerinde & operatörünü kullanarak veya bir struct literal ile doğrudan adres operatörünü kullanarak bir struct işaretçisi (pointer) oluşturabilirsiniz.
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
ptr := &p // mevcut struct'a işaretçi
// Veya doğrudan oluşturun
ptr2 := &Person{Name: "Bob", Age: 25}Go, bir işaretçi aracılığıyla struct alanlarına erişirken kullanışlı bir kısayol sağlar. (*ptr).Name yazmak yerine, doğrudan ptr.Name yazabilirsiniz. Go, işaretçiyi sizin için otomatik olarak dereference eder.
ptr := &Person{Name: "Alice", Age: 30}
// Her ikisi de aynı şekilde çalışır
fmt.Println((*ptr).Name) // açık dereference
fmt.Println(ptr.Name) // otomatik dereferenceBu otomatik başvuru çözme (dereferencing) işlemi, alanlar değiştirilirken de geçerlidir. İşaretçi (pointer) üzerinden yapılan değişiklikler orijinal yapıyı (struct) etkiler.
p := Person{Name: "Alice", Age: 30}
ptr := &p
ptr.Age = 31 // orijinali değiştirir
fmt.Println(p.Age) // 31Struct işaretçileri, Go'nun OOP desenlerinde temel öneme sahiptir. Bunlar, metotların alıcı (receiver) durumunu değiştirmesine olanak tanır, büyük struct'ların fonksiyonlara verimli bir şekilde aktarılmasını sağlar ve ağaçlar ile listeler gibi bağlı veri yapıları oluşturmanın temelini oluşturur.
Görev
KolayStruct pointer'ların orijinal verileri verimli bir şekilde değiştirmenize nasıl olanak tanıdığını gösteren bir banka hesabı sistemi oluşturalım. Pointer işlemleri aracılığıyla güncellenebilen bir hesap oluşturacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
account.go:Owner(string),Balance(float64) veAccountNumber(string) alanlarına sahip birBankAccountstruct'ı tanımlayın. Parametre olarak bir sahip adı ve hesap numarası alan ve 0 başlangıç bakiyesiyle yeni birBankAccountpointer'ı döndürenNewAccountadında bir fonksiyon oluşturun. Ayrıca bir*BankAccountpointer'ı ve bir miktar alan, ardından bu miktarı pointer aracılığıyla hesabın bakiyesine ekleyen birDepositfonksiyonu oluşturun.main.go: Girdiden hesap bilgilerini okuyun, oluşturucu fonksiyonunuzu (bir pointer döndüren) kullanarak bir hesap oluşturun, pointer'ı kullanarak bir para yatırma işlemi yapın ve bakiyenin değiştirildiğini onaylamak için hesap ayrıntılarını görüntüleyin.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Sahip adı (Owner name)
- Satır 2: Hesap numarası (Account number)
- Satır 3: Yatırılacak miktar (Deposit amount - float)
Çıktı formatı:
Account: [AccountNumber]
Owner: [Owner]
Balance: [Balance]Örneğin, John Smith, ACC-12345 ve 500.50 verildiğinde, çıktınız şöyle olmalıdır:
Account: ACC-12345
Owner: John Smith
Balance: 500.50NewAccount fonksiyonunuzun & operatörünü kullanarak *BankAccount döndürmesi gerektiğini ve Deposit fonksiyonunuzun Go'nun otomatik dereferencing özelliği sayesinde (örneğin, (*account).Balance yerine account.Balance) bakiyeyi doğrudan pointer üzerinden değiştirebileceğini unutmayın.
Kopya kağıdı
Bir struct pointer'ı, bir struct örneğinin bellek adresini tutar. & operatörünü kullanarak struct pointer'ları oluşturun:
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
ptr := &p // mevcut struct'a pointer
// Veya doğrudan oluşturun
ptr2 := &Person{Name: "Bob", Age: 25}Go, bir pointer üzerinden struct alanlarına erişirken otomatik dereferencing (adres çözümleme) sağlar. (*ptr).Name yerine ptr.Name yazabilirsiniz:
ptr := &Person{Name: "Alice", Age: 30}
// Her ikisi de aynı şekilde çalışır
fmt.Println((*ptr).Name) // açık dereference
fmt.Println(ptr.Name) // otomatik dereferenceBir pointer üzerinden yapılan değişiklikler orijinal struct'ı etkiler:
p := Person{Name: "Alice", Age: 30}
ptr := &p
ptr.Age = 31 // orijinali değiştirir
fmt.Println(p.Age) // 31Struct pointer'ları, metotların alıcı (receiver) durumunu değiştirmesine olanak tanır, büyük struct'ların fonksiyonlara verimli bir şekilde aktarılmasını sağlar ve bağlı veri yapılarının temelini oluşturur.
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Sahip adını oku
ownerName, _ := reader.ReadString('\n')
ownerName = strings.TrimSpace(ownerName)
// Hesap numarasını oku
accountNumber, _ := reader.ReadString('\n')
accountNumber = strings.TrimSpace(accountNumber)
// Yatırılacak tutarı oku
amountStr, _ := reader.ReadString('\n')
amountStr = strings.TrimSpace(amountStr)
amount, _ := strconv.ParseFloat(amountStr, 64)
// TODO: NewAccount fonksiyonunu kullanarak yeni bir hesap oluşturun (bir işaretçi döndürür)
// TODO: Hesap işaretçisini kullanarak Deposit fonksiyonu ile para yatırın
// TODO: Hesap ayrıntılarını istenen formatta yazdırın:
// Account: [AccountNumber]
// Owner: [Owner]
// Balance: [Balance]
}
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