Değer ile Geçme ve Referans ile Geçme
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 21 / 107.
Go, değer ile aktarılan (pass-by-value) bir dildir. Bir değişkeni bir fonksiyona aktardığınızda, Go bu değerin bir kopyasını oluşturur. Bu, fonksiyon içindeki değişikliklerin orijinal değişkeni etkilemeyeceği anlamına gelir.
func double(n int) {
n = n * 2
}
func main() {
x := 10
double(x)
fmt.Println(x) // 10 (değişmedi)
}Aynı durum struct'lar için de geçerlidir. Bir struct'ı bir fonksiyona geçirmek, tüm alanlarını kopyalar; bu nedenle fonksiyon içindeki değişiklikler kaybolur.
type Person struct {
Name string
Age int
}
func birthday(p Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(alice)
fmt.Println(alice.Age) // 30 (değişmedi)
}Özgün değeri değiştirmek için bunun yerine bir işaretçi geçirin. İşaretçinin kendisi kopyalanır, ancak yine de aynı bellek adresini gösterir ve özgün veriyi değiştirmenize olanak tanır.
func birthday(p *Person) {
p.Age++
}
func main() {
alice := Person{Name: "Alice", Age: 30}
birthday(&alice)
fmt.Println(alice.Age) // 31 (değiştirildi!)
}Özgün değeri değiştirmeniz gerektiğinde veya maliyetli kopyalama işleminden kaçınmak için büyük yapıları geçirirken işaretçileri kullanın. Özgün verileri istenmeyen değişikliklerden korumak istediğinizde değerleri kullanın.
Görev
KolayDeğer ile işaretçi üzerinden yapı geçirme arasındaki farkı gösteren bir alışveriş sepeti sistemi oluşturalım. Yalnızca işaretçi parametrelerinin özgün verileri değiştirebildiğini kendi gözlerinle göreceksin.
Kodunu iki dosyaya ayıracaksın:
cart.go:CartItem(string),Name(float64) vePrice(int) alanlarına sahip birQuantityyapısı tanımla. Miktarı güncellemeyi deneyen iki işlev oluştur:UpdateQuantityByValue, birCartItem(değer ile) ve yeni bir miktar alır, ardından öğenin miktarını yeni değere ayarlarUpdateQuantityByPointer, bir*CartItem(işaretçi) ve yeni bir miktar alır, ardından öğenin miktarını yeni değere ayarlar
Totalüzerinde fiyatın miktarla çarpımını döndüren birCartItemmetodu oluştur.main.go: Öğe bilgilerini girdiden oku, bir CartItem oluştur, ardından her iki güncelleme yaklaşımını göster. Önce değer işleviyle güncellemeyi dene ve sonucu göster, ardından işaretçi işleviyle güncelle ve sonucu tekrar göster.
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Öğe adı
- 2. satır: Fiyat (ondalık sayı)
- 3. satır: Başlangıç miktarı (tam sayı)
- 4. satır: Ayarlanacak yeni miktar (tam sayı)
Çıktı biçimi:
Initial: [Name] x[Quantity] = $[Total]
After value update: [Name] x[Quantity] = $[Total]
After pointer update: [Name] x[Quantity] = $[Total]Örneğin Laptop, 999.99, 1 ve 3 verildiğinde çıktın şöyle olmalıdır:
Initial: Laptop x1 = $999.99
After value update: Laptop x1 = $999.99
After pointer update: Laptop x3 = $2999.97Değer ile yapılan güncellemeden sonra miktarın 1 olarak kaldığına (işlev bir kopyayı değiştirdi), ancak işaretçi ile yapılan güncellemeden sonra 3 olarak değiştiğine (işlev özgün veriyi değiştirdi) dikkat et. Toplamları iki ondalık basamakla biçimlendir.
Kendin dene
package main
import (
"fmt"
)
func main() {
// Girdiyi oku
var name string
var price float64
var initialQty, newQty int
fmt.Scanln(&name)
fmt.Scanln(&price)
fmt.Scanln(&initialQty)
fmt.Scanln(&newQty)
// TODO: Giriş değerleriyle bir CartItem oluşturun
// TODO: Şu formatı kullanarak başlangıç durumunu yazdırın:
// fmt.Printf("Initial: %s x%d = $%.2f\n", ...)
// TODO: UpdateQuantityByValue kullanarak miktarı güncellemeyi deneyin
// Ardından sonucu yazdırın (miktarın değişmediğine dikkat edin)
// TODO: UpdateQuantityByPointer kullanarak miktarı güncelleyin
// Ardından sonucu yazdırın (miktarın değişeceğine dikkat edin)
}
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 PoolKendi başına pratik yap: Online Go derleyicisi