Golang嵌套切片中delete元素的奇怪行为

时间:2019-02-11 09:31:07

标签: go

我正在从事golang项目。我正在尝试从现有切片中维护一个切片,其中我的新切片不包含现有切片元素。我已经尝试过像这样的代码:

package main

import (
    "fmt"
    "reflect" 
)


func main(){
    savedArr := make(map[string][]int)
    newArr := make(map[string][]int)
    days := []string{"saturday", "friday", "sunday"}
    newSpotsArr := []int{10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101}
    savedArr["saturday"] = []int{10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101}
    savedArr["friday"] = []int{10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101}
    for _, day := range days{
        newArr[day] = newSpotsArr
    }
    for day, newSpots := range newArr{
        fmt.Println("day", day)
        fmt.Println("Top within loop", newSpots)
        for _, oldSpot := range savedArr[day]{
            exists, idx := InArray(oldSpot, newSpots)
            if exists {
                newSpots = append(newSpots[:idx], newSpots[idx + 1:]...)
            }
        }
        fmt.Println("Bottom within loop", newSpots)
    }
}

func InArray(val interface{}, array interface{}) (exists bool, index int) {
    exists = false
    index = -1
    switch reflect.TypeOf(array).Kind() {
        case reflect.Slice:
            s := reflect.ValueOf(array)
            for i := 0; i < s.Len(); i++ {
                if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
                    index = i
                    exists = true
                    return
                }
            }
    }
    return
}

其输出类似于:

day saturday
Top within loop [10 20 30 40 50 60 70 80 90 100 101]
Bottom within loop []
day friday
Top within loop [101 101 101 101 101 101 101 101 101 101 101]
Bottom within loop [101 101 101 101 101 101 101 101 101 101]
day sunday
Top within loop [101 101 101 101 101 101 101 101 101 101 101]
Bottom within loop [101 101 101 101 101 101 101 101 101 101 101]
finalArr map[friday:[101 101 101 101 101 101 101 101 101 101] sunday:[101 101 101 101 101 101 101 101 101 101 101] saturday:[]]

我无法理解它的工作方式。我期望它的输出应该像:

day saturday
Top within loop [10 20 30 40 50 60 70 80 90 100 101]
Bottom within loop []
day friday
Top within loop [10 20 30 40 50 60 70 80 90 100 101]
Bottom within loop []
day sunday
Top within loop [10 20 30 40 50 60 70 80 90 100 101]
Bottom within loop [10 20 30 40 50 60 70 80 90 100 101]
finalArr map[friday:[] sunday:[10 20 30 40 50 60 70 80 90 100 101] saturday:[]]

有人能说出它是如何工作的吗? 以及如何实现所需的输出

1 个答案:

答案 0 :(得分:1)

由于所有newArr[day]newSpotsArr具有相同的基础数组,因此代码无法正常工作。您需要通过制作新的切片来复制newSportsArr并将数据复制到其中:

for _, day := range days {
    newArr[day] = make([]int, len(newSpotsArr))
    copy(newArr[day], newSpotsArr)
}

游乐场:https://play.golang.org/p/kv-B9NnKqVd

更新:

Go中的

slice是引用类型。在slice的内部有3个内容:lencap和一个ptrptr是指向内存(基础数组)的指针。当您运行newArr[day]=newSpotsArr时,将复制所有三个值,这意味着newArr[day]指向与newSpotsArr相同的基础数组。因此,如果您运行newSpotsArr[0]=-100,则所有切片将看到该更改。

另请参阅:https://blog.golang.org/go-slices-usage-and-internals