I will like to understand why when I copy a struct value into an interface it behaves like it does. In this code can someone help me understand why when I copy the value from mySlice into foo3 it behaves different than the other copies?
package main
import (
"fmt"
"unsafe"
)
type SliceOfInt []int
// when passing a slice to a method you are passing this data. Lets prove it
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
// Print the header of a slice. Its Data. Len and Cap
func GetHeaderOfSliceOfInt(s unsafe.Pointer) *SliceHeader {
// this header needs to point to &mySlice but compiler will not let us. we have to use unsafe pointers
var header *SliceHeader
pointerToMySlice := s
header = ((*SliceHeader)(pointerToMySlice))
return header
}
func main() {
// On go everything is passed by coping values. When you pass a slice to a function you are passing this:
// reference: https://stackoverflow.com/a/39993797/637142
/*
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
*/
// create a new slice
var mySlice SliceOfInt = make([]int, 0)
mySlice = append(mySlice, 123456789) // append this number to mySlice
// now we have a slice with len:1 and capacity:1. Lets prove it
header := GetHeaderOfSliceOfInt(unsafe.Pointer(&mySlice))
fmt.Println(*header)
// this prints: {824635465728 1 1}
// this means that on memory address 824635465728 there is an array with cap:1 and len:1
// copy that header to someOtherSlice
someOtherSlice := mySlice
header = GetHeaderOfSliceOfInt(unsafe.Pointer(&someOtherSlice))
fmt.Println(*header)
// prints the same value {824635465728 1 1}
// anyways if I go to address 824635465728 on my computer I shoul dbe able to find integer 123456789
pointerToInteger := unsafe.Pointer((*header).Data)
var integerVal *int = ((*int)(pointerToInteger))
fmt.Println(*integerVal)
// if I copy like this, it will print the correct header {824635465728 1 1}
foo1 := mySlice
fmt.Println(*GetHeaderOfSliceOfInt(unsafe.Pointer(&foo1)))
// copy like this will also print the correct header {824635465728 1 1}
foo2 := foo1
fmt.Println(*GetHeaderOfSliceOfInt(unsafe.Pointer(&foo2)))
// If I copy like this it will print the incorrect header. Why?
var foo3 interface{} = mySlice
fmt.Println(*GetHeaderOfSliceOfInt(unsafe.Pointer(&foo3)))
// this last line prints {4746976 824635330392 0}
}
The output of the program is:
{824635465728 1 1}
{824635465728 1 1}
123456789
{824635465728 1 1}
{824635465728 1 1}
{4746976 824635330392 0}
Edit
I know that if I cast foo3 as: foo3.(SliceOfInt)
it will work. But why is that?