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

Board index Программирование GoLand

Description: Программирование на языке Go

#1by mexan » 26.01.2025, 12:03

Как работает append?
Функция append добавляет элементы в срез и возвращает новый срез. Однако есть нюанс: если емкость исходного среза достаточна, append изменит его. Если нет — создаст новый срез с новым базовым массивом.
Code: Select all
package main

import "fmt"

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

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

Как избежать проблем?
  1. Создавать копии срезов
    Если вам нужно изменить срез, не затрагивая исходный, используйте функцию copy или явно создавайте новый срез.
    Code: Select all
    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]).
    Code: Select all
    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 не изменит исходный срез, проверьте его емкость.
    Code: Select all
    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)
       }
    }
Image
mexan
Администратор
Reputation: 0
Posts: 136
Topics: 110

Return to GoLand

cron