Назад к вопросам
Senior
2
a := []int{1} // *T &1111000 len cap fmt.Println(len(a), cap(a)) // 1 1 b := append(a, 2) // *T &1111001 fmt.Println(len(b), cap(b)) // 2 2 b[0] = 0 fmt.Println(a) // [1] fmt.Println(b) // [1 2] c := append(b, 3) // [1 2 3] len = 3, cap = 4 // *T &1111011 ? d := append(c, 4) // [1 2 3 4] // len = 4, cap = 4 // *T &1111011 ? c[0] = 100 fmt.Println(b) // fmt.Println(c) // fmt.Println(d) //
Компании, где спрашивали
CRTEX
Ответ от нейросети
sobes.tech AI
В Go срезы (slice) — это структура, которая содержит указатель на массив, длину и емкость. При использовании append поведение зависит от текущей емкости среза.
Разберём пример:
package main
import "fmt"
func main() {
a := []int{1} // len=1, cap=1
fmt.Println(len(a), cap(a)) // 1 1
b := append(a, 2) // len=2, cap=2, новый массив выделен
fmt.Println(len(b), cap(b)) // 2 2
b[0] = 0
fmt.Println(a) // [1] - a не изменился, т.к. b указывает на новый массив
fmt.Println(b) // [0 2]
c := append(b, 3) // len=3, cap=4, емкость увеличилась, новый массив
d := append(c, 4) // len=4, cap=4, емкость не изменилась, массив тот же
c[0] = 100
fmt.Println(b) // [0 2] - b и c указывают на разные массивы
fmt.Println(c) // [100 2 3 4]
fmt.Println(d) // [100 2 3 4] - d и c указывают на один массив
}
Объяснение:
- При
appendесли емкость среза недостаточна, выделяется новый массив, и данные копируются. - Если емкость позволяет,
appendизменяет существующий массив. - В примере
bпосле первогоappendуказывает на новый массив, поэтому изменениеb[0]не влияет наa. - При
appendкcемкость увеличилась, выделился новый массив. - При
appendкdемкость была достаточна, поэтомуcиdуказывают на один массив, изменениеc[0]видно и вd.
Таким образом, важно понимать, что срезы могут разделять или не разделять underlying array в зависимости от емкости и операций append.