Ko’rsatkich (pointer) — o’zgaruvchining qiymatini emas, uning xotiradagi manzilini saqlaydigan tur. Go’da ko’rsatkichlar C++’dagiga o’xshaydi, lekin muhim farq bilan: Go’da ko’rsatkich arifmetikasi yo’q — manzilga son qo’shib-ayirib bo’lmaydi, bu xavfsizlikni oshiradi.
Ko’rsatkich —
*Turshaklida yoziladigan, boshqa o’zgaruvchining manzilini saqlovchi qiymat.&operatori manzilni oladi,*esa o’sha manzildagi qiymatga murojaat qiladi (dereference).
Manzil olish va dereference
package main
import "fmt"
func main() {
son := 42
korsatkich := &son
fmt.Println(son)
fmt.Println(*korsatkich)
*korsatkich = 100
fmt.Println(son)
}
42
42
100
&son — sonning xotiradagi manzilini oldi, korsatkich shu manzilni saqlaydi. *korsatkich — o’sha manzildagi qiymatni o’qiydi (42). *korsatkich = 100 esa manzil orqali asl sonning o’zini o’zgartirdi — shuning uchun keyingi sonni chop etish 100 berdi.
Ko’rsatkichni chop etish — manzilning o’zi
Agar ko’rsatkichning o’zini (dereference qilmasdan) chop etsangiz, u xotiradagi manzilni ko’rsatadi:
package main
import "fmt"
func main() {
son := 42
korsatkich := &son
fmt.Println(korsatkich)
}
0xc00011a010
Bu — son joylashgan xotira manzili (har safar ishga tushirilganda boshqacha bo’lishi mumkin). Amaliyotda ko’rsatkichning o’zini chop etish kamdan-kam foydali — odatda *korsatkich orqali qiymatning o’zi kerak bo’ladi.
nil ko’rsatkich
Hech qanday manzilga ishora qilmagan ko’rsatkichning zero value’si — nil. Uni dereference qilishga urinish dasturni qulatadi:
package main
import "fmt"
func main() {
var p *int
fmt.Println(*p)
}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x...]
goroutine 1 [running]:
main.main()
...
exit status 2
var p *int — pga hech qanday manzil berilmadi, u nil. *p esa mavjud bo’lmagan manzildagi qiymatni o’qishga urindi — bu ijro vaqtidagi jiddiy xato (panic). Ko’rsatkich bilan ishlashdan oldin uning nil emasligini tekshirish yaxshi amaliyot hisoblanadi.
Struct’ga ko’rsatkich — avtomatik dereference
Struct’ga ko’rsatkich orqali maydonga murojaat qilinganda, Go C++’dagi -> o’rniga oddiy nuqtani ishlatishga ruxsat beradi:
package main
import "fmt"
type Foydalanuvchi struct {
Ism string
}
func main() {
u := Foydalanuvchi{Ism: "Farrux"}
p := &u
p.Ism = "Master Sherkulov"
fmt.Println(u.Ism)
}
Master Sherkulov
p.Ism — to’liq yozilsa (*p).Ism bo’lishi kerak edi, lekin Go buni avtomatik bajaradi. p.Ism = "..." orqali qilingan o’zgarish asl uda ham ko’rindi, chunki p uning aynan o’ziga ishora qiladi. Bu naqsh keyingi darsda struct metodlarini o’rganishda markaziy ahamiyat kasb etadi.