Неожиданные побочные эффекты при использовании append



Работа со срезами в Go кажется простой, но функции, такие как append, могут приводить к неожиданным побочным эффектам, если не учитывать их особенностей



Пример:

func modifySlice(slice []int) {

slice = append(slice, 4)

fmt.Println("Inside function:", slice) // [1, 2, 3, 4]

}



func main() {

originalSlice := []int{1, 2, 3}

modifySlice(originalSlice)

fmt.Println("Outside function:", originalSlice) // [1, 2, 3]

}


На первый взгляд может показаться, что вызов append внутри функции изменит исходный срез. Но это не так! Причина в том, что append может создать новый массив, если емкости исходного среза недостаточно, и вернуть ссылку на новый массив, оставляя оригинальный срез неизменным



Как исправить:



Чтобы избежать путаницы и явно модифицировать исходный срез, передавайте указатель на срез:

func modifySlice(slice *[]int) {

*slice = append(*slice, 4)

fmt.Println("Inside function:", *slice) // [1, 2, 3, 4]

}



func main() {

originalSlice := []int{1, 2, 3}

modifySlice(&originalSlice)

fmt.Println("Outside function:", originalSlice) // [1, 2, 3, 4]

}




Важные моменты:



🔹append может изменить размер и емкость среза. Если емкости хватает, исходный массив модифицируется; если нет — создаётся новый массив.

🔹Чтобы избежать побочных эффектов, помните, что срезы — это ссылки на массивы, но функции, такие как append, могут менять поведение



⚡️Советы:



🔹Если нужно модифицировать исходный срез, работайте с указателями.

🔹Учитывайте, что append не гарантирует модификацию оригинального массива, если емкость среза исчерпана.



👉 @juniorGolang | #заметки