Go'da İşaretçi Temelleri
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 19 / 107.
Bir pointer, başka bir değişkenin bellek adresini saklayan bir değişkendir. Bir değeri doğrudan tutmak yerine, o değerin bellekte bulunduğu konumu tutar. Pointer'lar Go için temeldir ve verimli veri manipülasyonu için gereklidir.
Bir işaretçi oluşturmak için, bir değişkenin adresini almak üzere & operatörünü ve bir işaretçi türü bildirmek veya o adresteki değere erişmek için * operatörünü kullanın.
x := 42
p := &x // p, x'in bellek adresini tutar
fmt.Println(p) // 0xc000018030 (bellek adresi)
fmt.Println(*p) // 42 (o adresteki değer)& operatörü "adresi" anlamına gelir ve bir işaretçi döndürür. * operatörü, bir işaretçi üzerinde kullanıldığında "konumundaki değer" anlamına gelir ve dereferencing olarak adlandırılır. Ayrıca işaretçi aracılığıyla orijinal değeri değiştirebilirsiniz.
x := 10
p := &x
*p = 25 // değeri işaretçi aracılığıyla değiştir
fmt.Println(x) // 25 (orijinal değişken değişti)İşaretçi türü, T işaret edilen tür olmak üzere *T şeklinde yazılır. Bir int işaretçisinin türü *int'tir.
var p *int // int türünde bir işaretçi (pointer) tanımlar
x := 100
p = &x // p artık x'i işaret ediyorBir işaretçinin (pointer) sıfır değeri nil'dir, yani hiçbir şeyi işaret etmediği anlamına gelir. Bir nil işaretçisinin değerine erişmeye (dereference) çalışmak bir çalışma zamanı paniğine (runtime panic) neden olur, bu nedenle işaretçilerin kullanılmadan önce her zaman başlatıldığından (initialized) emin olun.
Görev
KolayDeğişkenleri bellek adresleri üzerinden değiştirmek için pointer'ların gücünü gösteren basit bir değer değiştirici (value swapper) oluşturalım.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
swap.go: Parametre olarak iki adet*intpointer alanSwapValuesadında bir fonksiyon oluşturun. Bu fonksiyon, bu pointer'ların işaret ettiği değerleri birbiriyle değiştirmelidir; fonksiyon çağrıldıktan sonra her değişken diğerinin orijinal değerini tutmalıdır. Fonksiyon herhangi bir değer döndürmez; değerleri doğrudan pointer'lar aracılığıyla değiştirir.main.go: Girdiden iki tam sayı okuyun, bunları değişkenlerde saklayın ve ardından değerlerini değiştirmek içinSwapValuesfonksiyonunuzu kullanın. Değişikliği göstermek için her iki değeri de değiştirmeden önce ve değiştirdikten sonra yazdırın.
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Birinci tam sayı
- Satır 2: İkinci tam sayı
Çıktı formatı:
Before: a=[first] b=[second]
After: a=[first] b=[second]Örneğin, 10 ve 25 verildiğinde, çıktınız şu şekilde olmalıdır:
Before: a=10 b=25
After: a=25 b=10Değişkenlerinizi fonksiyona aktarırken & operatörünü, fonksiyon içinde ise gerçek değerlere erişmek ve bunları değiştirmek için * operatörünü kullanmayı unutmayın.
Kopya kağıdı
Bir pointer (işaretçi), başka bir değişkenin bellek adresini saklayan bir değişkendir. Bir değişkenin adresini almak için & operatörünü, bir pointer türü tanımlamak veya o adresteki değere erişmek için * operatörünü kullanın.
x := 42
p := &x // p, x'in bellek adresini tutar
fmt.Println(p) // 0xc000018030 (bellek adresi)
fmt.Println(*p) // 42 (o adresteki değer)& operatörü "adresi" anlamına gelir ve bir pointer döndürür. * operatörü, bir pointer üzerinde kullanıldığında "adresteki değer" anlamına gelir ve buna dereferencing (referans çözme) denir.
Orijinal değeri pointer aracılığıyla değiştirebilirsiniz:
x := 10
p := &x
*p = 25 // pointer aracılığıyla değeri değiştir
fmt.Println(x) // 25 (orijinal değişken değişti)Pointer türü, T işaret edilen tür olmak üzere *T şeklinde yazılır:
var p *int // int türünde bir pointer tanımlar
x := 100
p = &x // p artık x'i işaret ediyorBir pointer'ın sıfır değeri (zero value) nil'dir. Bir nil pointer'ın referansını çözmeye çalışmak (dereference) çalışma zamanı paniğine (runtime panic) neden olur.
Kendin dene
package main
import "fmt"
func main() {
// Girişten iki tam sayı oku
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Değişimden önceki değerleri yazdır
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: a ve b işaretçileri ile SwapValues fonksiyonunu çağır
// Adresleri geçirmek için & operatörünü kullanmayı unutma
// Değişimden sonraki değerleri yazdır
fmt.Printf("After: a=%d b=%d\n", a, b)
}
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