dsbiw2911188 2019-02-11 09:31
浏览 78
已采纳

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

I am working on a golang project. I am trying to maintain a slice from a existing slice where my new slice does not contain the existing slice element. I have tried the code like :

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
}

Its output is like:

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:[]]

I am not able to understand how it is working. I was expecting its output should be like:

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:[]]

Can anybody tell how it is working? And how I can achieve my desired output

  • 写回答

1条回答 默认 最新

  • duanbu1998 2019-02-11 10:15
    关注

    The code is not working as expected because all newArr[day] has a same underlying array as newSpotsArr. You need to make a copy of newSportsArr by make a new slice and copy data into it:

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

    Playground: https://play.golang.org/p/kv-B9NnKqVd

    UPDATE:

    slice in Go is a reference type. Under the hood, slice keeps 3 things: len,cap,and a ptr. The ptr is a pointer to a memory (underlying array). when you run newArr[day]=newSpotsArr, all three value is copied, which means, newArr[day] points to the same underlying array as newSpotsArr. So if you run newSpotsArr[0]=-100, all slices will see the that change.

    See also: https://blog.golang.org/go-slices-usage-and-internals

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 fluent无法启动
  • ¥15 孟德尔随机化r语言运行问题
  • ¥15 pyinstaller编译的时候出现No module named 'imp'
  • ¥15 nirs_kit中打码怎么看(打码文件是csv格式)
  • ¥15 怎么把多于硬盘空间放到根目录下
  • ¥15 Matlab问题解答有两个问题
  • ¥15 LCD12864中文显示
  • ¥15 在使用CH341SER.EXE时不小心把所有驱动文件删除了怎么解决
  • ¥15 gsoap生成onvif框架
  • ¥15 有关sql server business intellige安装,包括SSDT、SSMS。