从地图值附加切片不会影响地图

mp := map[int][]int{}
slice := make([]int, 0, 1)
fmt.Printf("slice address:%p
", slice)
mp[0] = slice
slice = append(slice, 1)
fmt.Println("after append")
fmt.Printf("slice address:%p
", slice)
fmt.Println("slice:", slice)
fmt.Println("mp[0]:", mp[0])
fmt.Printf("mp[0] address:%p
", mp[0])  

output:

slice address:0xc042008f78  
after append  
slice address:0xc042008f78  
slice: [1]  
mp[0]: []  
mp[0] address:0xc042008f78

The address of the slice does not change as its cap is large enough during append. So why the map value does not take effect?

This is caused by the fact, that multiple slices can be backed by the same data but use different "sections" of the data. This means, that yes, an element is added to the data backing mp[0], but the length of the slice in mp is not changed. You can do that manually:

fmt.Println(mp[0][:1])

which does print [1].

You can grow any slice to it's capacity without changing the underlying data by using slice[:cap(slice)]. slice[:n] will panic if cap(slice) < n. slice[n] on the other hand will panic when len(slice) <= n. I assume that the former is possible to allow the growing of slices without changing the underlying data (as far as that is possible). The latter, I would say, is "normal" behavior.

This also explains why mp[0][:2] panics, as cap(mp[0]) is 1.

For more details you might want to read this official blog post, as suggested by Flimzy.

In Golang it is mentioned in blog on Go Slices: usage and internals

Slicing does not copy the slice's data. It creates a new slice value that points to the original array. This makes slice operations as efficient as manipulating array indices. Therefore, modifying the elements (not the slice itself) of a re-slice modifies the elements of the original slice:

slice = append(slice, 1)

So in the above case it is creating a new slice with pointing to the same original underlying array. That is the reason it is showing the same address.

To get the data of underlying array pointed by slice use reflect with unsafe:

hdr := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
data := *(*[1]int)(unsafe.Pointer(hdr.Data)) 

Working code on Playground

As explained in Go Slices: usage and internals, two slices may point to the same memory location, but may have different len and cap attributes.