Sobes.tech
Junior

Ինչպես են աշխատում slices-ները Go-ում?

sobes.tech AI

Պատասխան AI-ից

Սլայսը՝ դա թեթև պատյան է զանգվածի վրա: Այն ինքնին տվյալներ չի պահում, այլ հղում է հիմնական զանգվածին:

Սլայսի կառուցվածքը՝

  • Հղում հիմնական զանգվածին: Հասցե առաջին տարրին հիշողության մեջ:
  • Երկարություն (Length): Սլայսի տարրերի քանակը:
  • Հավաքածու (Capacity): Հիմնական զանգվածի տարրերի քանակը, որոնք հասանելի են սլայսի սկզբից:
// Սլայսի հայտարարության օրինակ
var s []int
s = append(s, 1, 2, 3) // Տարրեր ավելացնել

// Սլայսի s-ի ներքին ներկայացումը (պարզեցված)
// struct SliceHeader {
//     Data uintptr // Հղում հիմնական զանգվածին
//     Len int      // Սլայսի երկարությունը
//     Cap int      // Սլայսի հավաքածուն
// }
  • Սլայս ստեղծելիս՝ make([]T, length, capacity) օգտագործելով՝ ստեղծվում է հիմնական զանգված նշված հավաքածուով և սլայս, որը հղում է անում նրան՝ նշված երկարությամբ:
  • Օգտագործելով սլայսի կտրվածքը (օրինակ՝ arr[low:high:max])՝ ստեղծվում է նոր սլայս, որը հղում է անում նույն հիշողության տարածքին, բայց այլ հղում, երկարություն և հավաքածու:
  • append գործողությունը կարող է հանգեցնել հիշողության վերաօգտագործման: Եթե ընթացիկ հավաքածուն բավարար չէ նոր տարրեր ավելացնելու համար, Go-ն ստեղծում է մեծացրած հիմնական զանգված, պատճենում է հին զանգվածի տարրերը և թարմացնում սլայսի հղումը նոր զանգվածին: Սա կոչվում է reallocation:
  • Սլայսները փոխանցվում են արժեքով, բայց քանի որ դրանք պարունակում են հղում՝ հիմնական զանգվածին, փոփոխությունները (մասամբ կամ ամբողջությամբ) տեսանելի են բոլոր սլայսների վրա, որոնք հղում են անում նույն զանգվածին:
  • Սլայսի երկարության փոփոխությունը կտրվածքով՝ չի ազդում հիմնական զանգվածի վրա, բայց կարող է սահմանափակել տվյալների մուտքը:
Գծագրություն Երկարություն (Length) Հավաքածու (Capacity)
Հիմնավորում Իրական տարրերի քանակը Առավելագույն տարրերի քանակը՝ առանց վերաօգտագործման
Մուտքագումար Օգտագործվում է տարրերի մուտքագրման համար (s[i]) Կարգավորում է, թե որքան էլի տարր կարող է ավելացվել append-ով՝ վերաօգտագործումից առաջ
Ստանալը len(s) cap(s)
// Օրինակ՝ աշխատել հավաքածուի և երկարության հետ
s := make([]int, 0, 5) // Երկարություն՝ 0, հավաքածու՝ 5
fmt.Println(len(s), cap(s)) // 0 5

s = append(s, 1, 2) // 2 տարր ավելացնել
fmt.Println(len(s), cap(s)) // 2 5

s = append(s, 3, 4, 5, 6) // ևս 4 տարր ավելացնել՝ անհրաժեշտ է վերաօգտագործում
fmt.Println(len(s), cap(s)) // 6 10 (հավաքածուն մեծացել է)