TL;DR: (summary)
You just need to make a copy of the slice value. A value of slice type is a descriptor to an underlying array:
slice2 := slice
Now slice2
will refer to the same, shared underlying array and so it will be reachable after slice
is zerored.
In long:
slice := make([]int, 5)
This creates a local variable named slice
of type []int
(and will be initialized with a descriptor referring to an array of size 5
created in the background by make
). It's a slice which is a descriptor to a contiguous part of an underlying array which is created automatically in the background.
slicesArray[0] = &slice
This stores the address of the local variable (named slice
) into the 0th element of slicesArray
. Note that slicesArray
is just a slice of pointers (which pointers may point to values of type []int
but that doesn't matter now).
So still no copy of the original slice
is created.
And so when you zero the only value of type []int
(which is the local variable named slice
), you zero the only slice value (and you'll lose the only reference to its backing array).
You want to keep the slice value after slice
has been zeroed? Just make a copy of it (of the slice value). Copying a value of slice type only makes a copy of the descriptor, the backing array is not copied; and the copy will refer to the same backing array (it's shared):
slice2 := slice // makes a copy of the slice value
slice = nil
After this *(slicesArray[0])
will still point to a slice value being nil
, but we have a copy of the original slice (and the shared backing array).
So doing:
slicesArray[0] = &slice2
fmt.Println((*(slicesArray[0]))[3])
Will print again 25
. Go Playground
Should you keep slice values or pointers to slices?
Since slices are just descriptors which are relatively small, you should keep and work with slice values. A slice value already contains a "reference" to a backing array. Adding another indirection by using a pointer to a slice just complicates and slightly slows things down. A slice is already designed to be small, efficient and flexible (compared to "real" arrays in Go).
Of course a pointer to a slice value may also be useful in some cases, for example if you would ever want to create a function similar to the builtin append()
function without returning the new slice. Or when you create a custom type whose underlying type is a slice type, and you define methods for this type which modify the slice value (in this case a pointer receiver is necessary).
Further readings: (the docs explaining everything in detail)
Go Slices: usage and internals
Arrays, slices (and strings): The mechanics of 'append'