Welcome To Golang By Example

Understanding uintptr in Golang

Table of Contents

Overview

This is an unsigned integer type which is large enough to hold any pointer address. Therefore its size is platform dependent. It is just an integer representation of an address.

Properties

Purpose

uintptr can be used for below purposes:

Be careful that the above steps should be atomic with respect to Garbage Collector, otherwise it could lead to issues. For eg after the first step 1, the referenced object is liable to be collection. If that happens then after step 3, the pointer will be an invalid Go pointer and can crash the program. Look at the unsafe package documentation.

https://golang.org/pkg/unsafe/#Pointer

It lists down when the above conversion can be safe. See the below code for the scenario mentioned above.

In the below code we are doing arithmetic like below to get to address of field “b” in struct sample and then printing the value at that address. This below code is atomic with reference to the garbage collector.

p := unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Offsetof(s.b))
package main
import (
    "fmt"
    "unsafe"
)
type sample struct {
    a int
    b string
}
func main() {
    s := &sample{a: 1, b: "test"}
    
   //Getting the address of field b in struct s
    p := unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Offsetof(s.b))
    
    //Typecasting it to a string pointer and printing the value of it
    fmt.Println(*(*string)(p))
}

Output:

test

See below code where we are converting an unsafe.Pointer to uintptr and printing it. Also, note as mentioned before too one the unsafe.Pointer is converted to uinptr, the reference is lost and the reference variable can be garbage collected.

package main

import (
    "fmt"
    "unsafe"
)

type sample struct {
    a int
    b string
}

func main() {
    s := &sample{
        a: 1,
        b: "test",
    }
    //Get the address as a uintptr
    startAddress := uintptr(unsafe.Pointer(s))
    fmt.Printf("Start Address of s: %d\n", startAddress)
}

Output:

The output will be dependent upon the machine as it is an address.

Start Address of s: 824634330992