I am trying to learn how pointers work on go. Why is the following example not working?
package main
import (
"fmt"
"unsafe"
)
type SliceOfStrings []string
// function that creates an slice of []string
// returns interface{} cause I am interested on learning how pointers work
func Create() interface{} {
var mySlice1 SliceOfStrings = make([]string, 0)
mySlice1 = append(mySlice1, "str1")
mySlice1 = append(mySlice1, "str2")
// return a slice with as ["str1","str2"]
return mySlice1
}
func main() {
x := Create()
// 0xc000021940
fmt.Printf("address of x is %p \n", &x)
// get unsafe pointer to address of x
// unsafe pointer. Prints 0xc000021940
p1 := unsafe.Pointer(&x)
fmt.Println(p1)
// unsigned pointer. Prints 824633858368
p2 := uintptr(p1)
fmt.Println(p2)
// prints same value as p1 0xc000021940
p3 := unsafe.Pointer(p2)
fmt.Println(p3)
// Make p4 point to same address as 0xc000021940
p4 := (*SliceOfStrings)(p3)
//fmt.Println(p4)
// why this does not print "str1" ??
fmt.Println((*p4)[0])
// I get error: runtime error: invalid memory address or nil pointer dereference
}
CodePudding user response:
Create()
returns a value of type interface{}
, so type of x
is interface{}
, so type of &x
is *interface{}
, and not *SliceOfStrings
. So x
points to an interface{}
value and not to a SliceOfStrings
value!
If you type assert SliceOfStrings
from the return value of Create()
, it works:
x := Create().(SliceOfStrings)
Also add runtime.KeepAlive(x)
at the end of your main()
, because if you don't refer to x
anymore, it can be garbage collected at any time.
With this change it works and outputs str1
. Try it on the Go Playground.
In general, stay away from package unsafe
as much as possible. You can learn and use pointers without package unsafe
. Only think of unsafe
as a last-last resort!