use unsafe pointer to get value from a []string

Issue

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
}

Solution

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!

Answered By – icza

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.