In golang, slice and map are both reference types. When you simply need to modify elements in slice/map, the modification to slice/map members will be "broadcasted" to all slices. E.g, given m1 := make(map[int]int); m2 := m1
, m1[3] = 5
will lead to m2[3] == 5
.
However, when you try to add new elements into these two types, things start to differ. As is shown in the example below, the new elements added into a map param will be shown automatically in the argument; however, the new elements added into a slice, are 'discarded' in the argument.
Question is, why is this difference?
func editMap(m map[int]int) {
m[3] = 8
m[4] = 9
}
func editSlice(s []int) {
s = append(s, 5)
s = append(s, 9)
}
func main() {
m := make(map[int]int, 0)
m[1] = 5
m[2] = 3
fmt.Printf("%v\n", m) //map[1:5 2:3]
editMap(m)
fmt.Printf("%v\n", m) //map[1:5 2:3 3:8 4:9]
s := make([]int, 2)
s[0] = 2
s[1] = 5
fmt.Printf("%v\n", s) //[2 5]
editSlice(s)
fmt.Printf("%v\n", s) //[2 5]
}
Edit: I may not be clear on the intention of this question and please let me rephrase it(sorry for this and thanks for all the internal details).
What I really want to ask is, apparently map is implemented as a pointer to hide all details for the hash map; why wasn't slice implemented similarly?
The current slice implementation is indeed quite lightweight, however, from an API point of view (API between golang users like us and golang maintainers like Ross Cox), the APIs of these two 'reference' types are not that uniform and may lead to pitfalls for developers new to golang.