Darsliklar Go Lang Slice

Go Lang Go Lang Slice

Slice — Go’da amaliyotda eng ko’p ishlatiladigan to’plam turi. Massivdan farqli, uning o’lchami qat’iy emas — u kerak bo’lganda o’sadigan, moslashuvchan “ko’rinish” (view)dir.

Slicemassiv ustidagi moslashuvchan qatlam bo’lib, o’z ichida ko’rsatkich (pointer), uzunlik (len) va sig’im (cap) saqlaydi. Bir nechta slice bitta massivni birga “ko’rishi” mumkin.

Slice yaratish

Slice massivga o’xshab yoziladi, lekin kvadrat qavs ichida o’lcham ko’rsatilmaydi:

package main

import "fmt"

func main() {
    mevalar := []string{"olma", "anor", "uzum"}
    fmt.Println(mevalar)
    fmt.Println(len(mevalar))

    boshqa := make([]int, 3)
    fmt.Println(boshqa)
}
[olma anor uzum]
3
[0 0 0]

[]string{...} — literal orqali to’g’ridan-to’g’ri qiymat bilan yaratish. make([]int, 3) — 3 ta zero-value elementdan iborat bo’sh slice yaratadi. [N]Tur (massiv) bilan []Tur (slice) o’rtasidagi yagona yozuv farqi — kvadrat qavs ichidagi sondir, lekin ma’nosi butunlay boshqacha.

append — slice’ni kengaytirish

Slice’ga element qo’shish uchun o’rnatilgan append funksiyasi ishlatiladi:

package main

import "fmt"

func main() {
    sonlar := []int{1, 2, 3}
    sonlar = append(sonlar, 4)
    sonlar = append(sonlar, 5, 6)

    fmt.Println(sonlar)
}
[1 2 3 4 5 6]

append natijani qaytaradi — shuning uchun uni har doim sonlar = append(sonlar, ...) shaklida, qaytgan qiymatni asl o’zgaruvchiga qayta yozib ishlatish shart. Buning sababi keyingi bo’limda ochiladi.

len va cap — sig’im qanday o’sadi

Har bir slice ikkita o’lchamga ega: len (hozirgi elementlar soni) va cap (joriy massivda joy tugamasdan qancha sig’ishi mumkinligi). Sig’im tugaganda Go slice’ni avtomatik, kattaroq yangi massivga ko’chiradi:

package main

import "fmt"

func main() {
    s := make([]int, 0, 2)
    for i := 0; i < 5; i++ {
        s = append(s, i)
        fmt.Println(len(s), cap(s))
    }
}
1 2
2 2
3 4
4 4
5 8

Boshlang’ich sig’im — 2. Uchinchi element qo’shilganda joy yetmay qoldi va Go sig’imni avtomatik ikki baravayga (4) oshirdi; beshinchi elementda yana ikki baravayga (8). Bu — nega appendning natijasini qaytarib olish shart ekanining sababi: sig’im tugasa, slice butunlay yangi massivga ko’chadi.

Slice — reference turi

Massivdan farqli, ikkita slice bitta massivni “ulashishi” mumkin — bittasida qilingan o’zgarish ikkinchisida ham ko’rinadi:

package main

import "fmt"

func main() {
    original := []int{1, 2, 3}
    nusxa := original
    nusxa[0] = 100

    fmt.Println(original)
    fmt.Println(nusxa)
}
[100 2 3]
[100 2 3]

nusxa := original massivdagi kabi mustaqil nusxa yaratmadi — ikkalasi ham bitta xotiradagi massivga ishora qiladi. nusxa[0]ni o’zgartirish originalda ham ko’rindi. Mustaqil nusxa kerak bo’lsa, buning uchun maxsus copy() funksiyasi ishlatiladi.