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
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