2 回答

TA贡献1828条经验 获得超13个赞
当你有一个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]
),新切片将与原始切片共享支持数组。这意味着如果您修改新切片的元素,原始切片也会观察到这些更改。因此,如果您从新切片中删除一个元素并将元素复制到被删除元素的位置,则原始切片的最后一个元素仍将在那里,它被原始切片“覆盖”。通常的做法是将最后一个元素置零,以便垃圾收集器可以回收它的内存,如果它是指针类型(或“类似”如切片、映射或通道)。
我怎样才能避免有一个“输出切片”?(以正确的方式打印,包含正确的元素,具有预期的长度和容量)
正如这个答案中所述:您必须将一个指针传递给您的切片,并修改 中的指向值FindAndRemoveFromFooSlice()
,因此您不必返回新切片。
为什么我尝试“删除就地”导致“输入切片”的长度与过滤过程之前的长度相同?
你从来没有修改过原始切片,你传递了它所以制作了一个副本,并且在内部FindAndRemoveFromFooSlice()
你只能修改副本(但你甚至没有修改副本)。你返回一个新的切片,但你没有分配它,所以原来的切片(头)是完整的。
为什么“输入切片”的长度与我应用过滤过程之前的长度相同?如何进行删除操作以更改“输入切片”的长度?
前两个问题回答了这个问题。

TA贡献1770条经验 获得超3个赞
最小工作代码示例(带有注释以提供一些上下文):
// use a pointer for the input slice so then it is changed in-place
func FindAndRemoveFromFooSliceInPlace(iFilter int, inSl *[]FooItem) *FooItem {
pointedInSl := *inSl // dereference the pointer so then we can use `append`
inLen := len(pointedInSl)
for idx, elem := range pointedInSl {
if elem.Id == iFilter {
log.Printf("Loop ID %v", idx)
// check these docs: https://github.com/golang/go/wiki/SliceTricks#delete
pointedInSl = append(pointedInSl[:idx], pointedInSl[idx+1:inLen]...)
pointedInSl = pointedInSl[:inLen-1]
*inSl = pointedInSl // assigning the new slice to the pointed value before returning
return &elem
}
}
return nil
}
- 2 回答
- 0 关注
- 182 浏览
添加回答
举报