我进行了以下测试,即打印原始输入切片(过滤后),而没有删除元素,但是最后有一个额外的元素,使输入切片具有相同的长度,即使过滤后应该较短。
我已经看过这篇文档https://github.com/golang/html" target="_blank">go/wiki/SliceTricks#delete
但是我认为我缺少有关Go的一些技巧,因为似乎我使用的切片方法错误。
这是代码:
package foo
import (
"fmt"
"log"
"math/rand"
"testing"
)
type FooItem struct {
Id int
Category string
Value float64
}
const minRand = 0
const maxRand = 10
const maxSliceLen = 3
var inFooSlice []FooItem
func init() {
for i := 1; i <= maxSliceLen; i++ {
inFooSlice = append(inFooSlice, FooItem{
Id: i,
Category: "FooCat",
Value: minRand + rand.Float64()*(maxRand-minRand),
})
}
}
// this is the function I am testing
func FindAndRemoveFromFooSlice(iFilter int, inSl []FooItem) (*FooItem, []FooItem) {
inLen := len(inSl)
outSl := make([]FooItem, inLen)
for idx, elem := range inSl {
if elem.Id == iFilter {
log.Printf("Loop ID %v", idx)
// check these docs: https://github.com/golang/go/wiki/SliceTricks#delete
outSl = inSl[:idx+copy(inSl[idx:], inSl[idx+1:inLen])]
outSl = outSl[:inLen-1]
return &elem, outSl
}
}
return nil, nil
}
func TestFoo(t *testing.T) {
fmt.Printf("\nOriginal (PRE) slice\n")
fmt.Println(inFooSlice)
fmt.Println(len(inFooSlice))
fmt.Println(cap(inFooSlice))
idFilter := 1
fePtr, outFooSlice := FindAndRemoveFromFooSlice(idFilter, inFooSlice)
fmt.Printf("\nOriginal (POST) slice\n")
fmt.Println(inFooSlice)
fmt.Println(len(inFooSlice))
fmt.Println(cap(inFooSlice))
fmt.Printf("\nFiltered element\n")
fmt.Println(*fePtr)
fmt.Printf("\nOutput slice\n")
fmt.Println(outFooSlice)
fmt.Println(len(outFooSlice))
fmt.Println(cap(outFooSlice))
}
这是测试执行的输出:
$ go test -v -run TestFoo
=== RUN TestFoo
Original (PRE) slice
[{1 FooCat 6.046602879796196} {2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904}]
3
4
2019/05/31 12:53:30 Loop ID 0
Original (POST) slice
[{2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904} {3 FooCat 6.645600532184904}]
3
4
Filtered element
{1 FooCat 6.046602879796196}
Output slice
[{2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904}]
2
4
--- PASS: TestFoo (0.00s)
PASS
ok git.openenergi.net/scm/flex/service/common 0.008s
更新“输入切片作为指针”
OK,假设我要处理原始输入切片,即没有副本或输出切片。
pointedInSl[inLen-1] = FooItem{}
)这是代码:
func FindAndRemoveFromFooSliceInPlace(iFilter int, inSl *[]FooItem) *FooItem {
pointedInSl := *inSl
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[inLen-1] = FooItem{} // why this throws a runtime "panic: runtime error: index out of range" ???
pointedInSl = pointedInSl[:inLen-1]
return &elem
}
}
return nil
}
func TestFooInPlace(t *testing.T) {
fmt.Printf("\nOriginal (PRE) slice\n")
fmt.Println(inFooSlice)
fmt.Println(len(inFooSlice))
fmt.Println(cap(inFooSlice))
idFilter := 1
fePtr := FindAndRemoveFromFooSliceInPlace(idFilter, &inFooSlice)
fmt.Printf("\nOriginal (POST) slice\n")
fmt.Println(inFooSlice)
fmt.Println(len(inFooSlice))
fmt.Println(cap(inFooSlice))
fmt.Printf("\nFiltered element\n")
fmt.Println(*fePtr)
}
这是奇怪的输出:
$ go test -v -run TestFooInPlace
=== RUN TestFooInPlace
Original (PRE) slice
[{1 FooCat 6.046602879796196} {2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904}]
3
4
2019/05/31 16:32:38 Loop ID 0
Original (POST) slice
[{2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904} {3 FooCat 6.645600532184904}]
3
4
Filtered element
{1 FooCat 6.046602879796196}
--- PASS: TestFooInPlace (0.00s)
PASS
ok git.openenergi.net/scm/flex/service/common 0.007s
我建议对icza答案进行编辑,以在其底部提供一个最小的工作代码示例,以说明他提供的有用信息。被拒绝,指出它作为编辑是没有意义的,它应该被写为评论或答案,所以就在这里(主要归功于icza):
最低工作代码示例(带注释的内容):
// 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
}
我正在使用这个命令从切片中删除一个元素,但它不起作用,请建议。
问题内容: 我最近学习了Go语言,现在对以下代码感到困惑: 结果: 问题答案: c是从数组中获取的一个切片b。这不是副本,而只是的两个前两个元素的窗口b。 由于b容量为5,c可以扩展到其他3个位置(实际上,它会创建一个新的切片,但位于内存中的同一位置)。 切片的最大容量是底层数组的容量减去切片在数组中起始位置的大小: func main() { b := make([]int, 0, 5) c :
本文向大家介绍Golang slice切片操作之切片的追加、删除、插入等,包括了Golang slice切片操作之切片的追加、删除、插入等的使用技巧和注意事项,需要的朋友参考一下 本文介绍了Golang slice切片操作之切片的追加、删除、插入等,分享给大家,具体如下: 一、一般操作 1,声明变量,go自动初始化为nil,长度:0,地址:0,nil 2,切片的追加,删除,插入操作 3,copy的
问题内容: 这个带有添加功能的删除技巧如何工作? 似乎它正在抓取第一个元素(空数组)之前的所有内容 然后将所有内容附加在第一个元素之后(位置零) …(点对点)有什么作用? 问题答案: 切片在哪里,是要删除的元素的索引: 是Go中可变参数的语法。 基本上,在 定义 函数时,它将把您传递的所有参数放入该类型的一个切片中。这样,您可以传递任意数量的参数(例如,可以传递任意数量的参数)。 现在,当 调用
主要内容:从开头位置删除,从中间位置删除,从尾部删除Go语言并没有对删除切片元素提供专用的语法或者接口,需要使用切片本身的特性来删除元素,根据要删除元素的位置有三种情况,分别是从开头位置删除、从中间位置删除和从尾部删除,其中删除切片尾部的元素速度最快。 从开头位置删除 删除开头的元素可以直接移动数据指针: 也可以不移动数据指针,但是将后面的数据向开头移动,可以用 append 原地完成(所谓原地完成是指在原有的切片数据对应的内存区间内完成,不会导致
问题内容: 我有一个结构“ Guest”,其中包含聚会客人的元数据(唯一的ID,名称,姓氏以及作为该客人的朋友的客人的唯一ID的列表。 我有以下代码从朋友列表中删除ID: 问题是:我要删除的元素被元素的移位覆盖,但是切片不会变短。而是将切片的最后一个元素相乘。 举一个例子:是。我打电话后,结果却不是理想的。 那么,我在做什么错呢? 问题答案: 任何打算/确实修改接收器的方法都必须使用指针接收器。