Skip to content

Instantly share code, notes, and snippets.

@Integralist
Last active July 30, 2019 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Integralist/d84389ff35687f7c9d89d5246338fa38 to your computer and use it in GitHub Desktop.
Save Integralist/d84389ff35687f7c9d89d5246338fa38 to your computer and use it in GitHub Desktop.
[Go Access Underlying Slice Array] #go #golang #slice #array #unsafe #reflect #header
package main
import (
"fmt"
"reflect"
"unsafe"
)
func main() {
// define a slice
s := []int{1, 2, 3, 4}
// access the underlying array of the slice
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s))
data := *(*[4]int)(unsafe.Pointer(hdr.Data))
// display the slice internals
fmt.Printf("s: %#v\n", s)
fmt.Printf("hdr: %#v\n", hdr)
fmt.Printf("data %#v\n", data)
// create a new zero-value slice based on same proportions as the original slice
newSlice := make([]int, len(s), cap(s))
fmt.Printf("\nnewSlice: %#v\n", newSlice)
// copy the original slice into the new slice
copy(newSlice, s)
fmt.Printf("newSlice: %#v\n", newSlice)
// access the underlying array of the new slice
hdrNew := (*reflect.SliceHeader)(unsafe.Pointer(&newSlice))
dataNew := *(*[4]int)(unsafe.Pointer(hdr.Data))
// display the new slice internals (notice there's a different underlying array!)
fmt.Printf("\nnewSlice: %#v\n", newSlice)
fmt.Printf("hdrNew: %#v\n", hdrNew)
fmt.Printf("dataNew %#v\n", dataNew)
// now modify the new slice contents (which should change the underlying array)
newSlice[0] = 123
fmt.Printf("\nnewSlice modified: %#v\n", newSlice)
// reacquire the underlying array of the original slice (just so we can be sure we've not modified things)
hdrOriginal := (*reflect.SliceHeader)(unsafe.Pointer(&s))
dataOriginal := *(*[4]int)(unsafe.Pointer(hdr.Data))
// display the original slice internals (again, for the sake of comparison -- notice the memory address is the same still)
fmt.Printf("\noriginal s: %#v\n", s)
fmt.Printf("hdrOriginal: %#v\n", hdrOriginal)
fmt.Printf("dataOriginal %#v\n", dataOriginal)
}
/*
s: []int{1, 2, 3, 4}
hdr: &reflect.SliceHeader{Data:0x414020, Len:4, Cap:4}
data [4]int{1, 2, 3, 4}
newSlice: []int{0, 0, 0, 0}
newSlice: []int{1, 2, 3, 4}
newSlice: []int{1, 2, 3, 4}
hdrNew: &reflect.SliceHeader{Data:0x414090, Len:4, Cap:4}
dataNew [4]int{1, 2, 3, 4}
newSlice modified: []int{123, 2, 3, 4}
original s: []int{1, 2, 3, 4}
hdrOriginal: &reflect.SliceHeader{Data:0x414020, Len:4, Cap:4}
dataOriginal [4]int{1, 2, 3, 4}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment