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.
Slice — massiv 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.