I have the following code
package main
import "fmt"
func main() {
a := []int{1}
b := &a[0]
fmt.Println(a, &a[0], b, *b) // prints [1] 0xc00001c030 0xc00001c030 1
a = append(a, 1, 2, 3)
fmt.Println(a, &a[0], b, *b) // prints [1 1 2 3] 0xc000100020 0xc00001c030 1
}
First it creates a slice of 1 int. Its len is 1 and cap is also 1. Then I take a pointer to its first element and get the underlying pointer value in print. It works fine, as expected.
Than I add 3 more elements to the slice making go expand the capacity of the slice, thus copying it to another place in memory. After that I print the address (by taking a pointer) of the slice's first element which is now different from address stored in b
.
However, when I then print the underlying value of b
it also works fine. I don't understand why does it work. As far as I know the slice to which first element b
points to was copied to another place in memory, so its previous memory must have been released. However, it seems to still be there.
If we look on maps, golang doesn't even allow us to create pointers on element by key because of the exact same problem - underlying data can be moved to another place in memory. However, it works perfectly fine with slices. Why is it so? How does it really works? Is the memory not being freed because there still is a variable which points to this memory? How is it different from maps?