NOTE
1.8 unsafe
Pointer types in Go, why pointers are needed, the unsafe pointer type, examples, and the underlying APIs.
This is a historical learning note and may contain outdated or incomplete understanding.
1. Pointer Types
1.1. What They Are
The address of a variable.
1.2. Why Pointer Types Are Needed
Using pointer types allows the callee to modify the value passed by the caller.
func double(x int) {
x += x
}
func main() {
var a = 3
double(a)
fmt.Println(a) // 3
}
// Modified version
func double(x *int) {
*x += *x
x = nil
}
func main() {
var a = 3
double(&a)
fmt.Println(a) // 6
p := &a
double(p)
fmt.Println(a, p == nil) // 12 false
}
1.3. Golang Pointer Types
Golang pointer types are safe.
- Mathematical operations cannot be performed on them
- Pointers of different types cannot be converted into each other
- Pointers of different types cannot be compared using
==or!= - Pointer variables of different types cannot be assigned to each other
2. unsafe
2.1. What It Is
An unsafe pointer type.
2.2. Usage
Safe pointer types cannot be used for arithmetic. They can first be converted to unsafe.Pointer, then converted to uintptr for arithmetic.
2.2.1. Get the Length of a slice
func TestUnsafe1(t *testing.T) {
s := make([]int, 9, 20)
//Len: &s => pointer => uintptr => pointer => *int => int
var Len = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))
fmt.Println(Len, len(s))
//Cap: &s => pointer => uintptr => pointer => *int => int
var Cap = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16)))
fmt.Println(Cap, cap(s))
}
// output
9 9
20 20
2.2.2. Get the Length of a map
func TestUnsafe2(t *testing.T) {
mp := make(map[string]int)
mp["qcrao"] = 100
mp["stefno"] = 18
//&mp => pointer => **int => int
count := **(**int)(unsafe.Pointer(&mp))
fmt.Println(count, len(mp))
}
// output
2 2
2.2.3. Convert between string and []byte
func TestUnsafe3(t *testing.T) {
bytes := []byte{104, 101, 108, 108, 111}
p := unsafe.Pointer(&bytes) // forcibly convert to unsafe.Pointer; the compiler will not report an error
str := *(*string)(p) // then forcibly convert to a pointer to string, and read the pointed-to value as a string
fmt.Println(str) // output "hello
}
2.3. Implementation
- Data structure
type ArbitraryType int
type Pointer *ArbitraryType// similar to void* in C
- Methods
// Return the number of bytes occupied by type x, excluding the size of the content pointed to by x
func Sizeof(x ArbitraryType) uintptr
// Return the byte offset of a struct member from the start of the struct; the argument must be a struct member
func Offsetof(x ArbitraryType) uintptr
// Return m, where m means that when a type is memory-aligned, its allocated memory address is divisible by m
func Alignof(x ArbitraryType) uintptr
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub