Skip to content

Instantly share code, notes, and snippets.

@vcabbage
Last active October 27, 2016 19:36
Show Gist options
  • Save vcabbage/cb5cdafb1b6f926528cd877d90ea0a89 to your computer and use it in GitHub Desktop.
Save vcabbage/cb5cdafb1b6f926528cd877d90ea0a89 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"unsafe"
)
// sliceHeader is the in memory structure of a slice
type sliceHeader struct {
// Data is the pointer to the underlying array
Data uintptr
// Len and Cap are the len and cap of the slice
Len int
Cap int
}
func main() {
// Create a slice of bytes, containing 5 elements
x := []byte{1, 2, 3, 4, 5}
// Make a copy of x as y
y := x
// Print out the address and contents of the two slices
fmt.Printf("Before mutating x:\n")
fmt.Printf("x Address: %p Contents: % x\n", &x, x)
fmt.Printf("y Address: %p Contents: % x\n", &y, y)
// Pass x to a func that mutates the slice
mutate(x)
// Print out the address and contents of the two slices after mutating
fmt.Printf("\nAfter mutating x:\n")
fmt.Printf("x Address: %p Contents: % x\n", &x, x)
fmt.Printf("y Address: %p Contents: % x\n", &y, y)
// Use unsafe to get a reference to the slice headers
xHeader := (*sliceHeader)(unsafe.Pointer(&x))
yHeader := (*sliceHeader)(unsafe.Pointer(&y))
// Print out the contents of the headers
fmt.Printf("\nContents of the slice headers:\n")
fmt.Printf("x {Data: %#x, Len: %d, Cap: %d}\n", xHeader.Data, xHeader.Len, xHeader.Cap)
fmt.Printf("y {Data: %#x, Len: %d, Cap: %d}\n", yHeader.Data, yHeader.Len, yHeader.Cap)
// Use unsafe to get a reference to the underlying array
array := (*[5]byte)(unsafe.Pointer(xHeader.Data))
// Print out the contents of the array
fmt.Printf("\nContents of array the data fields are pointing to:\n")
fmt.Printf("array Address: %p Contents: % x\n", array, *array)
// Change the array
array[2] = 0xff
// Print out the address and contents of the two slices after mutating
fmt.Printf("\nAfter mutating the underlying array:\n")
fmt.Printf("x Address: %p Contents: % x\n", &x, x)
fmt.Printf("y Address: %p Contents: % x\n", &y, y)
// Attempt to mutate the array in a function
mutateArray(*array)
// Print out the address and contents of the two slices after mutating
fmt.Printf("\nAfter attempting to mutate array in mutateArray():\n")
fmt.Printf("x Address: %p Contents: % x\n", &x, x)
fmt.Printf("y Address: %p Contents: % x\n", &y, y)
}
// mutate changes the 3rd element (index 2) of a slice of bytes to 0
func mutate(b []byte) {
fmt.Printf("\nAddress of the slice inside mutate()\n")
fmt.Printf("b Address: %p\n", &b)
b[2] = 0
}
// mutateArray changes the 3rd element (index 2) of a 5 element array of bytes to 0xAA
func mutateArray(a [5]byte) {
fmt.Printf("\nAddress of the array inside mutateArray()\n")
fmt.Printf("a Address: %p\n", &a)
a[2] = 0xAA
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment