Ko'rsatkichlar
Go dasturlash tilida ko'rsatkichlar (pointers) xotira manzillari (memory addresses) bilan to'g'ridan-to'g'ri ishlash imkonini beradi. Ko'rsatkichlar orqali o'zgaruvchining xotiradagi manziliga murojaat qilish va uning qiymatini o'zgartirish mumkin.
& operatoriDasturda biror o'zgaruvchi yaratilganida, operativ xotiradan (RAM) unga ma'lum bir katakcha (xotira manzili) ajratiladi.
Go tilida o'zgaruvchining xotira manzilini olish uchun uning oldiga & (ampersand) belgisi qo'yiladi:
package main
import "fmt"
func main() {
var num int = 5
// O'zgaruvchining qiymatini chop etish
fmt.Println("O'zgaruvchi qiymati:", num)
// O'zgaruvchining xotira manzilini chop etish
fmt.Println("Xotira manzili:", &num)
}
Natija:
O'zgaruvchi qiymati: 5
Xotira manzili: 0xc000018030
0xc000018030 — bu num o'zgaruvchisi xotiraning qaysi katakchasida joylashganini ko'rsatuvchi 16-lik (hexadecimal) manzil.
Xotira manzilini saqlovchi maxsus o'zgaruvchi ko'rsatkich (pointer) deb ataladi. U ma'lumot turi oldiga * belgisini qo'yish orqali e'lon qilinadi:
var num int = 5
var ptr *int = &num
Bu yerda *int — bu ko'rsatkich butun son (int) turidagi o'zgaruvchining xotira manzilini saqlashini bildiradi.
package main
import "fmt"
func main() {
var name = "Ali"
var ptr *string
// name o'zgaruvchisining manzilini ptr ga o'zlashtiramiz
ptr = &name
fmt.Println("Ko'rsatkich qiymati (manzil):", ptr)
fmt.Println("O'zgaruvchi manzili:", &name)
}
Natija:
Ko'rsatkich qiymati (manzil): 0xc00007c1c0
O'zgaruvchi manzili: 0xc00007c1c0
* operatori)Ko'rsatkich saqlayotgan xotira manzilidagi qiymatni o'qish uchun uning oldiga * (dereferensiya operatori) qo'yiladi:
package main
import "fmt"
func main() {
var name = "Ali"
var ptr *string = &name
// *ptr orqali manzildagi asl qiymatni olamiz
fmt.Println("Asl qiymat:", *ptr) // Ali
}
Ko'rsatkich yordamida o'zgaruvchining xotiradagi asl qiymatini bevosita yangilash mumkin. Buning bosqichma-bosqich qanday ishlashini ko'rib chiqamiz.
1-qadam: O'zgaruvchilarni e'lon qilish
var num int
var ptr *int

Bu yerda biz int turidagi ptr ko'rsatkichini va oddiy num o'zgaruvchisini yaratdik. Ikkalasi ham hali initsializatsiya qilinmagani uchun ptr hech qanday manzilni ko'rsatmaydi.
2-qadam: Oddiy o'zgaruvchiga qiymat berish
num = 22

Bu num o'zgaruvchisiga 22 qiymatini beradi, ya'ni 22 numning xotira katakchasiga yoziladi.
3-qadam: Ko'rsatkichga manzil biriktirish
ptr = &num

Bu num o'zgaruvchisining xotira manzilini ptr ko'rsatkichiga biriktiradi.
4-qadam: O'zgaruvchi qiymatini bevosita o'zgartirish
num = 11

Bu numga 11 qiymatini beradi.
5-qadam: Ko'rsatkich orqali qiymatni o'zgartirish
*ptr = 2

Bu ko'rsatkich ptr ko'rsatib turgan xotira manzilidagi qiymatni bevosita o'zgartiradi — demak, numning qiymati ham o'zgaradi.
To'liq misol:
package main
import "fmt"
func main() {
var num int = 22
var ptr *int = &num
fmt.Println("Boshlang'ich num:", num) // 22
fmt.Println("ptr ko'rsatgan qiymat:", *ptr) // 22
// Ko'rsatkich orqali qiymatni o'zgartiramiz
*ptr = 2
fmt.Println("Yangilangan num:", num) // 2
fmt.Println("ptr ko'rsatgan qiymat:", *ptr) // 2
}
Natija:
Boshlang'ich num: 22
ptr ko'rsatgan qiymat: 22
Yangilangan num: 2
ptr ko'rsatgan qiymat: 2
*ptr = 2 amali bajarilganda, ptr ko'rsatib turgan xotira katagidagi qiymat to'g'ridan-to'g'ri 2 ga o'zgaradi, natijada num o'zgaruvchisining qiymati ham 2 bo'ladi.
nil ko'rsatkichlarAgar ko'rsatkich e'lon qilinib, unga hech qanday manzil biriktirilmasa, uning standart qiymati nil (bo'sh) bo'ladi:
package main
import "fmt"
func main() {
var ptr *int
fmt.Println("Ko'rsatkich qiymati:", ptr)
}
Natija:
Ko'rsatkich qiymati: <nil>
[!WARNING]
nilko'rsatkichni dereferensiya qilish (*ptrdeb qiymatini o'qishga urinish) dasturning to'xtab qolishiga (panic: runtime error: invalid memory address or nil pointer dereference) olib keladi.
new() funksiyasi yordamida ko'rsatkich yaratishGo tilida new() o'rnatilgan funksiyasi orqali ham yangi xotira ajratib ko'rsatkich olish mumkin:
package main
import "fmt"
func main() {
// new(int) int uchun xotira ajratadi va uning ko'rsatkichini qaytaradi
ptr := new(int)
// Manzilga qiymat yozamiz
*ptr = 20
fmt.Println("Xotira manzili:", ptr)
fmt.Println("Manzildagi qiymat:", *ptr)
}
Natija:
Xotira manzili: 0xc000016058
Manzildagi qiymat: 20
* operatorisiz ko'rsatkich yaratishGo tilida := (qisqa e'lon qilish) yordamida ko'rsatkich turi (*Tur) yozmasdan ham ko'rsatkich yaratish mumkin — Go kompilyatori turi avtomatik aniqlaydi:
package main
import "fmt"
func main() {
var name = "Ali"
// *string yozmasdan ham ptr ko'rsatkich bo'ladi
var ptr = &name
fmt.Println("ptr qiymati:", ptr)
fmt.Println("name manzili:", &name)
}
Natija:
ptr qiymati: 0xc0000101e0
name manzili: 0xc0000101e0
Bu yerda &name to'g'ridan-to'g'ri ptr o'zgaruvchisiga o'zlashtirilgan. * operatori yozilmagan bo'lsa-da, ptr baribir to'liq qonuniy ko'rsatkich hisoblanadi.