🎓 A1Learner
🔍
0 of 28 lessons completed

Go Unsafe Pointers

An unsafe pointer is a pointer that can point to a value of any type. It comes from the unsafe package, and it lets code reach memory in ways the compiler does not check.

Read and change through a round trip

A pointer to an int converts to unsafe.Pointer and back to a pointer to int. A write through that pointer changes the original value.

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	n := 10
	fmt.Println("Before:", n)
	p := unsafe.Pointer(&n)
	*(*int)(p) = 25
	fmt.Println("After:", n)
}

Read a field by its offset

uintptr holds an address as a plain number. unsafe.Offsetof gives the distance from the start of a struct to one of its fields. Adding the offset of Y to the address of the struct reaches the Y field.

package main

import (
	"fmt"
	"unsafe"
)

type Point struct {
	X int
	Y int
}

func main() {
	p := Point{X: 7, Y: 42}
	addr := uintptr(unsafe.Pointer(&p)) + unsafe.Offsetof(p.Y)
	y := *(*int)(unsafe.Pointer(addr))
	fmt.Println(y)
}

Read both fields by their offsets

Each field has its own offset from the same starting address. Two reads print both values in field order.

package main

import (
	"fmt"
	"unsafe"
)

type Point struct {
	X int
	Y int
}

func main() {
	p := Point{X: 7, Y: 42}
	base := uintptr(unsafe.Pointer(&p))
	x := *(*int)(unsafe.Pointer(base + unsafe.Offsetof(p.X)))
	y := *(*int)(unsafe.Pointer(base + unsafe.Offsetof(p.Y)))
	fmt.Println(x, y)
}

Example

package main

import (
	"fmt"
	"unsafe"
)

type Point struct {
	X int
	Y int
}

func main() {
	p := Point{X: 1, Y: 2}
	addr := uintptr(unsafe.Pointer(&p)) + unsafe.Offsetof(p.Y)
	*(*int)(unsafe.Pointer(addr)) = 99
	fmt.Printf("%v\n", p)
}

Key points

  • unsafe.Pointer can hold the address of a value of any type.
  • A pointer of any type converts to unsafe.Pointer, and unsafe.Pointer converts back to a pointer of any type.
  • uintptr holds an address as a number, so an offset can be added to it.
  • unsafe.Offsetof reports the distance in bytes from the start of a struct to one of its fields.
  • The compiler does not check this code.
  • A mistake can break the program in ways safe code cannot.

In this example, the program builds a Point with X set to 1 and Y set to 2. It adds the offset of Y to the address of the struct. It writes 99 through the pointer at that address. The print shows the whole struct, and Y now holds 99 while X stays 1.

Note

cgo is a tool that calls C code, and it sits outside this course.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Go Playground

Exercise

What happens when code writes through a pointer built from an address plus the offset of the Y field?