Search code examples
pointersgomemory-address

Accessing a Memory Address From a String in Go?


In golang, can I print the value of a memory address from a given string?

For example, if run the following code:

a := "A String"
fmt.Println(&a)

It prints 0x1040c108.

How could I take a string such as 0x1040c108 and print the value of that string stored in the memory? Something like fmt.Println(*0x1040c108)

Is this possible?


Solution

  • This can be done, but it is a really really REALLY bad idea. Anytime you are importing the unsafe package, you are either doing something wrong, or something really hardcore. I'm hesitant to even answer this, but here goes.

    https://play.golang.org/p/unkb-s8IzAo

    package main
    
    import (
        "fmt"
        "strconv"
        "unsafe"
    )
    
    func main() {
        // original example manually examined the printed address and used the value
        // updated to preserve forward compatibility due to runtime changes shifting the address over time
    
        hi := "HI"
    
        // getting address as string dynamically to preserve compatibility
        address := fmt.Sprint(&hi)
    
        fmt.Printf("Address of var hi: %s\n", address)
    
        // convert to uintptr
        var adr uint64
        adr, err := strconv.ParseUint(address, 0, 64)
        if err != nil {
            panic(err)
        }
        var ptr uintptr = uintptr(adr)
    
        fmt.Printf("String at address: %s\n", address)
        fmt.Printf("Value: %s\n", ptrToString(ptr))
    }
    
    func ptrToString(ptr uintptr) string {
        p := unsafe.Pointer(ptr)
        return *(*string)(p)
    }
    

    And yes, this was pretty much taken almost line for line from the unsafe godoc. https://godoc.org/unsafe

    Also note that if/when your memory reference is NOT a go string, everything will come crashing down catastrophically. And that go vet is configured to send you an angry message for doing this, reinforcing that this is indeed a bad idea.

    UPDATE: Updated example to run on playground as of go 1.15.1, which either the playground or go itself has changed the way the memory is addressed. Or the more likely case that changes in core libs/runtime will shift the address across versions. It now dynamically obtains the address vs a manually hardcoded value.