这有点奇怪,但这里的大多数答案都是危险的,并且掩盖了他们实际在做什么。查看有关从切片中删除项目的原始问题,正在制作切片的副本,然后将其填充。这可确保当切片在您的程序中传递时,您不会引入细微的错误。


这是一些比较用户在此线程和原始帖子中的答案的代码。这是一个可以在其中处理此代码的go playground。


基于附加的删除

package main


import (

    "fmt"

)


func RemoveIndex(s []int, index int) []int {

    return append(s[:index], s[index+1:]...)

}


func main() {

    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    removeIndex := RemoveIndex(all, 5)


    fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]

    fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]


    removeIndex[0] = 999

    fmt.Println("all: ", all) //[999 1 2 3 4 6 7 9 9]

    fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]

}

在上面的示例中,您可以看到我创建了一个切片并用数字 0 到 9 手动填充它。然后我们从所有中删除索引 5 并将其分配给删除索引。但是,当我们现在打印所有内容时,我们看到它也已被修改。这是因为切片是指向底层数组的指针。写出来,以removeIndex原因all被修改以及与该差值all是由不再从可到达的一个元件更长removeIndex。接下来我们改变一个值removeIndex,我们可以看到也all被修改了。Effective go对此进行了更详细的介绍。


下面的例子我不会进入,但它为我们的目的做了同样的事情。并且只是说明使用副本没有什么不同。


package main


import (

    "fmt"

)


func RemoveCopy(slice []int, i int) []int {

    copy(slice[i:], slice[i+1:])

    return slice[:len(slice)-1]

}


func main() {

    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    removeCopy := RemoveCopy(all, 5)


    fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]

    fmt.Println("removeCopy: ", removeCopy) //[0 1 2 3 4 6 7 8 9]


    removeCopy[0] = 999

    fmt.Println("all: ", all) //[99 1 2 3 4 6 7 9 9]

    fmt.Println("removeCopy: ", removeCopy) //[999 1 2 3 4 6 7 8 9]

}

问题原始答案

查看原始问题,它不会修改要从中删除项目的切片。对于大多数访问此页面的人来说,使该线程中的原始答案是迄今为止最好的。


package main


import (

    "fmt"

)


func OriginalRemoveIndex(arr []int, pos int) []int {

    new_arr := make([]int, (len(arr) - 1))

    k := 0

    for i := 0; i < (len(arr) - 1); {

        if i != pos {

            new_arr[i] = arr[k]

            k++

        } else {

            k++

        }

        i++

    }


    return new_arr

}


func main() {

    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    originalRemove := OriginalRemoveIndex(all, 5)


    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    fmt.Println("originalRemove: ", originalRemove) //[0 1 2 3 4 6 7 8 9]


    originalRemove[0] = 999

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    fmt.Println("originalRemove: ", originalRemove) //[999 1 2 3 4 6 7 8 9]

}

如您所见,此输出的行为符合大多数人的预期,并且可能是大多数人想要的。的修改originalRemove不会导致更改all,删除索引并分配它的操作也不会导致更改!极好的!


这段代码有点长,所以上面可以改成这样。


一个正确的答案

package main


import (

    "fmt"

)


func RemoveIndex(s []int, index int) []int {

    ret := make([]int, 0)

    ret = append(ret, s[:index]...)

    return append(ret, s[index+1:]...)

}


func main() {

    all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    removeIndex := RemoveIndex(all, 5)


    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]

    fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]


    removeIndex[0] = 999

    fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 9 9]

    fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]

}

几乎与原始的删除索引解决方案相同,但是我们在返回之前创建了一个新的切片来追加。