Если у вас есть переменная типа int
, и вы хотите написать функцию, которая увеличивает ее значение, как вы это делаете?Вы либо передаете указатель на переменную, либо возвращаете увеличенное значение, которое необходимо присвоить исходной переменной.
Например (попробуйте на Go Playground ):
func inc(i int) int { i++; return i }
var i int = 2
inc(i)
fmt.Println(i) // This will be 2
В приведенном выше коде вы передаете i
в inc()
, который увеличивает его и возвращает его значение.Оригинал i
, конечно, не изменится, i
внутри inc()
- это просто копия, независимая от оригинала i
.Чтобы оригинал изменился, вам нужно указать возвращаемое значение:
i = inc(i)
Или использовать указатели в первую очередь (попробуйте на Go Playground ):
func inc(i *int) { *i++ }
var i int = 2
inc(&i)
fmt.Println(i) // This will be 3
То же самое относится и к ломтикам.Если вы хотите / должны изменить заголовок слайса (который является указателем данных, длиной и емкостью, см. reflect.SliceHeader
), вы должны либо передать указатель на этот слайс (не очень часто), либоВы должны вернуть измененный новый заголовок среза, который вы должны назначить вызывающей стороне.Это решение используется чаще, таков подход, которому следует встроенный append()
.
Когда вы срезаете срез (например, someslice[min:max]
), новый срез будет разделенрезервный массив с оригинальным.Это означает, что если вы измените элементы нового среза, оригинал также будет наблюдать эти изменения.Таким образом, если вы удаляете элемент из нового слайса и копируете элементы на место удаленного элемента, последний элемент исходного слайса все равно будет там, который «покрыт» исходным слайсом.Обычной практикой является обнуление последнего элемента, чтобы сборщик мусора мог восстановить свою память, если это будет указатель типа (или «подобный», как фрагмент, карта или канал).Подробнее см. Утечка памяти в срезе golang и Идет ли сбор мусора на части срезов?
Чтобы ответить на ваши вопросы напрямую:
- как мне избежать "выходного среза"?(который напечатан правильным образом, содержит правильные элементы, с ожидаемой длиной и емкостью)
Как указано в этом ответе: вам нужно будет передать указатель на ваш срез,и измените указанное значение в FindAndRemoveFromFooSlice()
, так что вам не нужно возвращать новый фрагмент.
- , почему моя попытка «удалить на месте» приводит к «входному слайсу»"с той же самой длиной, которая была до процесса фильтрации?
Вы никогда не изменяли исходный фрагмент, вы передавали его, чтобы сделать копию, и внутри FindAndRemoveFromFooSlice()
вы можете изменять толькокопия (но вы даже не изменили копию).Вы возвращаете новый фрагмент, но не назначаете его, поэтому исходный фрагмент (заголовок) не поврежден.
- , почему «входной фрагмент» имеет ту же длину, что и раньшеприменять процесс фильтрации?Как сделать операцию удаления, чтобы изменить длину «входного среза»?
Ответ на предыдущие 2 вопроса.
См. Связанныйвопросы:
Проходят ли срезы Голанга по значению?
срез по сравнению с картой, которая будет использоваться в параметре