« Back to Index

[Go Access Underlying Slice Array]

View original Gist on GitHub

Tags: #go #golang #slice #array #unsafe #reflect #header

Go Access Underlying Slice Array.go

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}
*/