Tarkibga o'tish

Funksiya va ko‘rsatkichlar

Go funksiyaga berilgan argumentning qiymatini nusxalaydi. Ba’zan funksiya chaqiruvchidagi asl o‘zgaruvchini o‘zgartirishi yoki katta qiymatni nusxalashni kamaytirishi kerak. Bunday vaziyatda pointer parametr ishlatiladi.

Qiymat va pointer parametr

package main

import "fmt"

func qiymatBilanOzgartir(n int) {
    n = 100
}

func pointerBilanOzgartir(n *int) {
    *n = 100
}

func main() {
    son := 10
    qiymatBilanOzgartir(son)
    fmt.Println("Qiymatdan keyin:", son)

    pointerBilanOzgartir(&son)
    fmt.Println("Pointerdan keyin:", son)
}

Natija:

Qiymatdan keyin: 10
Pointerdan keyin: 100

Birinchi funksiya sonning nusxasini o‘zgartiradi. Ikkinchisiga &son, ya’ni manzil uzatiladi. nning o‘zi ham qiymat sifatida nusxalanadi, ammo nusxadagi manzil o‘sha songa qaraydi. *n = 100 shu manzildagi qiymatni yangilaydi.

Go’da C++ dagidek reference parametr yo‘q. Pointer — qiymat sifatida uzatiladigan manzil qiymatidir.

nilni xavfsiz boshqarish

Pointer parametr nil bo‘lishi mumkin. Funksiya shartiga qarab xato qaytarish yoki nilni alohida ma’no sifatida qabul qilish kerak:

package main

import (
    "fmt"
    "strings"
)

func tozalash(matn *string) error {
    if matn == nil {
        return fmt.Errorf("matn ko‘rsatkichi nil")
    }
    *matn = strings.TrimSpace(*matn)
    return nil
}

func main() {
    nom := "  Go dasturchi  "
    if err := tozalash(&nom); err != nil {
        fmt.Println("Xato:", err)
        return
    }
    fmt.Printf("%q\n", nom)
}

Natija:

"Go dasturchi"

Tekshiruvsiz *matn ishlatilsa, nil argument runtime’da panic beradi. Public API’da nilga munosabat hujjatlashtirilishi lozim.

Pointer qachon kerak?

Pointer quyidagi holatlarda asosli:

  • funksiya chaqiruvchidagi qiymatni o‘zgartirishi kerak;
  • katta struct nusxalanishini kamaytirish muhim va o‘lchov buni tasdiqlaydi;
  • nil “qiymat berilmagan” degan alohida holatni ifodalaydi;
  • bir obyektning umumiy holati bir nechta joydan boshqariladi.

Kichik son, bool yoki qisqa struct faqat “pointer tezroq” degan taxmin bilan pointerga aylantirilmaydi. Pointer nil holatini va umumiy o‘zgaruvchan holatni olib kiradi. Bu kodni tushunish va parallel ishlashni murakkablashtirishi mumkin.

Slice yoki map elementlarini o‘zgartirish uchun odatda *[]T yoki *map[K]V shart emas: ularning qiymati allaqachon asosiy ma’lumotga murojaat qiladi. Ammo slice’ning o‘z uzunligi yoki sig‘imini chaqiruvchi uchun almashtirish kerak bo‘lsa, yangilangan slice’ni qaytarish odatiy va ravshan usuldir.

Pointer qaytarish

Lokal o‘zgaruvchining manzilini qaytarish Go’da xavfsiz. Kompilyator qiymatning kerakli vaqtgacha yashashini ta’minlaydi:

func yangiSon() *int {
    n := 42
    return &n
}

Qiymat stack yoki heap’da joylashishini kompilyator escape analysis bilan hal qiladi. Kod semantikasini xotira joylashuvi haqidagi taxminga bog‘lamang.

Xulosa

  • Pointer parametr ham qiymat sifatida uzatiladi, lekin u asl qiymat manzilini saqlaydi.
  • *p orqali chaqiruvchidagi qiymat o‘zgartiriladi.
  • nil ehtimoli tekshirilishi yoki API shartida taqiqlanishi kerak.
  • Pointer semantika talab qilganda ishlatiladi; avtomatik performance yutug‘i deb qaralmaydi.

Keyingi darsda bir-biriga bog‘liq maydonlarni yangi turga birlashtiradigan struct o‘rganiladi.