unsafe.Pointer
- Go course
- Advanced
- Lesson 8/68
- 4 min
Learn the universal pointer with unsafe.Pointer.
unsafe.Pointer
unsafe.Pointer is a generic pointer that any pointer type can convert to. Normally you can't turn a *int64 into a *float64; with unsafe.Pointer in between you can read the same memory as another type.
f := 1.0
bits := *(*uint64)(unsafe.Pointer(&f))
fmt.Printf("%x\n", bits) // 3ff0000000000000math.Float64bits does exactly this inside a safe function.
The uintptr trap
uintptr holds an address as a number; the garbage collector doesn't treat it as a pointer. Storing an address in a uintptr and converting it back later can touch invalid memory if the object moved or was collected. If arithmetic is needed, convert and compute in the same expression.
p2 := unsafe.Pointer(uintptr(p) + off) // in one expressionPractice Read the bits
Declare f := 2.0. Convert it to *uint64 through unsafe.Pointer and print the value in hex with fmt.Printf("%x\n", ...).
Starter code
package main
import (
"fmt"
"unsafe"
)
func main() {
// buraya yaz
}Sample solution
package main
import (
"fmt"
"unsafe"
)
func main() {
f := 2.0
bits := *(*uint64)(unsafe.Pointer(&f))
fmt.Printf("%x\n", bits)
}Expected output
4000000000000000
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What is the correct way to convert <code>*T1</code> → <code>*T2</code>?
- T2(p)
- p.(T2)
- (*T2)(unsafe.Pointer(p)) Correct answer
- (*T2)(p)
Explanation: Different pointer types can't be converted directly; first convert to unsafe.Pointer, then to the target pointer type.
2 Generic pointer
x := int32(7)
p := (*uint32)(unsafe.____(&x))
x := int32(7)
p := (*uint32)(unsafe.Pointer(&x))
Explanation: unsafe.Pointer is the bridge between two pointer types.
3 Pointer kinds
| Term | Meaning |
|---|---|
*int |
Typed pointer |
unsafe.Pointer |
Untyped pointer |
uintptr |
Number holding an address |
math.Float64bits |
Safe bit reading |