Слайсы без ошибок

  • Автор темы Автор темы mexan
  • Дата начала Дата начала
Сообщения
202
Реакции
0
Как работает append?
Функция append добавляет элементы в срез и возвращает новый срез. Однако есть нюанс: если емкость исходного среза достаточна, append изменит его. Если нет — создаст новый срез с новым базовым массивом.
Код:
package main

import "fmt"

func main() {
	slice := []int{1, 2, 3}
	newSlice := append(slice, 4)
	slice[0] = 99
	fmt.Println(newSlice)
}

Возможные проблемы:
  • Если несколько срезов ссылаются на один базовый массив, изменение одного среза может повлиять на другие;
  • Если вы сохраняете ссылку на большой массив через под-срез, это может предотвратить сборку мусора для неиспользуемых данных;
  • Если вы предполагаете, что append всегда создает новый срез, это может привести к неожиданному поведению.

Как избежать проблем?
  1. Создавать копии срезов
    Если вам нужно изменить срез, не затрагивая исходный, используйте функцию copy или явно создавайте новый срез.
    Код:
    package main
    
    import "fmt"
    
    func main() {
    	original := []int{1, 2, 3}
    	copied := make([]int, len(original))
    	copy(copied, original)
    	copied[0] = 99
    	fmt.Println(original)
    	fmt.Println(copied)
    }
  2. Используйте полное выражение среза
    Если вы создаете под-срез и хотите контролировать его емкость, используйте полное выражение среза (slice[low:high:max]).
    Код:
    package main
    
    import "fmt"
    
    func main() {
    	original := []int{1, 2, 3, 4, 5}
    	subslice := original[1:4:4]
    	subslice = append(subslice, 6)
    	fmt.Println(original)
    	fmt.Println(subslice)
    }
  3. Проверяйте емкость перед использованием append
    Если вы хотите быть уверены, что append не изменит исходный срез, проверьте его емкость.
    Код:
    package main
    
    import "fmt"
    
    func main() {
    	slice := []int{1, 2, 3}
    	if cap(slice) == len(slice) {
    		newSlice := append(slice, 4)
    		fmt.Println(newSlice)
    	} else {
    		newSlice := append(slice, 4)
    		fmt.Println(newSlice)
    	}
    }
 
Назад
Сверху