Все три Println покажут [0 1 2 3] 4 5. Первый append создаёт другой массив, второй меняет скрытый пятый элемент общего массива.
Исследование поведения slice и функции append
Все три Println покажут [0 1 2 3] 4 5. Первый append создаёт другой массив, второй меняет скрытый пятый элемент общего массива.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Определите, какой вывод получит программа в каждом месте вызова Println, учитывая детали работы функции append, срезов и их ёмкости.
package main
import "fmt"
func main() {
slice := make([]string, 0, 5)
slice = append(slice, "0")
slice = append(slice, "1")
slice = append(slice, "2")
slice = append(slice, "3")
fmt.Println(slice, len(slice), cap(slice)) // ?
addToSlice1(slice)
fmt.Println(slice, len(slice), cap(slice)) // ?
addToSlice2(slice)
fmt.Println(slice, len(slice), cap(slice)) // ?
}
func addToSlice1(slice []string) {
slice = append(slice[:1:1], "one")
}
func addToSlice2(slice []string) {
slice = append(slice, "two")
}
Ответ
Все три Println покажут [0 1 2 3] 4 5. Первый append создаёт другой массив, второй меняет скрытый пятый элемент общего массива.
В addToSlice1 выражение slice[:1:1] ограничивает вместимость единицей. Добавление one требует нового массива и не затрагивает исходные элементы.
В addToSlice2 свободная вместимость есть: two записывается по индексу 4 общего массива. Внешняя длина остаётся 4, поэтому печать не показывает этот элемент. После второго вызова fmt.Println(slice[:5]) показал бы [0 1 2 3 two]. Копируется дескриптор среза, а не все данные.