Удаление элемента из слайса
Объясните поведение во второй строке. Изначально было два варианта:
- Вывод не изменится во втором случае
- Вывод изменится и последний элемент будет отсутствовать
Но оказался другой вариант. Как объяснить?
// You can edit this code!
// Click here and start typing.
package main
import "fmt"
type Item struct {
A int
B string
}
func remove(slice []*Item, s int) []*Item {
return append(slice[:s], slice[s+1:]...)
}
func main() {
x := make([]*Item, 0)
x = append(x, &Item{1, "2"})
x = append(x, &Item{2, "3"})
x = append(x, &Item{3, "4"})
x = append(x, &Item{4, "5"})
fmt.Println(x[0], x[1], x[2], x[3])
remove(x, 0)
fmt.Println(x[0], x[1], x[2], x[3])
x = remove(x, 3)
fmt.Println(x[0], x[1], x[2])
}
&{1 2} &{2 3} &{3 4} &{4 5}
&{2 3} &{3 4} &{4 5} &{4 5}
&{2 3} &{3 4} &{4 5} // тут была бы паника для третьекго элемента
Program exited.
Ответы (1 шт):
Руководство по языку Go, раздел Appending and copying slices
If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.
В функции remove массив, на который указывает slice, достаточно велик, чтобы хранить результат append-а. При вызове remove(x, 0) в функцию remove значение x было скопировано. Но скопирован был не сам массив, а его дескриптор - структура, содержащая указатель на массив, дескриптор типа и число элементов.
Поэтому, когда вы вызвали remove(x,0), операции производились на массиве, на который указывает x. В нем элементы с позиций 1,2,3 были скопированы на позиции 0,1,2. Элемент на позиции 3 остался доступным, так как в дескрипторе массива x написано "в массиве четыре элемента".
После вызова x = remove(x,3) в переменную x сохранён новый дескриптор массива, в котором написано "в массиве три элемента". В результате последний элемент перестал быть видным.