Go中unsafe.Pointer类型的使用小结

作者:

文章目录
  • 类型不兼容的指针转换(例如从 *int 转为 *float64) 与 uintptr 配合操作底层内存地址 修改只读字段(例如字符串的只读字节) 实现类似 C 的结构体偏移访问
  • unsafe.Pointer 和普通的 &T 指针(即 *T)在 Go 中有本质上的区别 类型 说明 *T 是类型安全的指针,指向类型 T 的数据。编译器知道它的类型信息,能自动进行内存对齐、类型检查等。 unsafe.Pointer 是一种通用的无类型指针,可以转换为任意类型的指针或从任意类型的指针转换过来。编译器不检查其指向的类型和用法。
  • package main import ( “fmt” “unsafe” ) func main() { var x int = 100 // 将 *int 转换为 *float64(不安全!仅用于演示) p := unsafe.Pointer(&x) f := (*float64)(p) // 假装 x 是 float64 fmt.Println(*f) // 输出不确定,因为解释方式不对 } ❗这是错误用法,仅作为类型转换的演示。实际运行会出现乱码或未定义行为。
  • package main import ( “fmt” “unsafe” ) type Person struct { age int score float64 } func main() { p := Person{age: 25, score: 98.5} // 获取结构体首地址 ptr := unsafe.Pointer(&p) // 偏移到第二个字段(score) scorePtr := (*float64)(unsafe.Pointer(uintptr(ptr) + unsafe.Offsetof(p.score))) fmt.Println(*scorePtr) // 输出:98.5 }
  • package main import ( “fmt” “reflect” “unsafe” ) func main() { s := “hello” sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) // 强转为字节数组指针修改内容 b := (*[5]byte)(unsafe.Pointer(sh.Data)) b[0] = ‘H’ fmt.Println(s) // 输出 “Hello” } ❗这是标准库明确禁止的行为,仅作教学展示。在某些平台上可能 crash!
  • 场景 是否安全 推荐使用 类型间转换(*T1 ➜ *T2) ❌ ❌ 与 uintptr 搭配偏移操作 ✅ ✅ 直接操作底层数据(如字符串修改) ❌ ❌ 到此这篇关于Go中unsafe.Pointer类型的使用小结的文章就介绍到这了,更多相关Go unsafe.Pointer类型内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Go语言中uintptr和unsafe.Pointer的区别的实现小结 Go 指针、uintptr、unsafe.Pointer之间如何转换 Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算 Golang 中的 unsafe.Pointer 和 uintptr详解
  • 目录
    • 🎯 使用场景
    • 和普通指针的区别
    • ✅ 示例 1:不同类型指针转换
    • ✅ 示例 2:uintptr与unsafe.Pointer配合做地址偏移(字段偏移)
    • ✅ 示例 3:修改字符串的只读内容(危险行为)
    • ✅ 小结

    unsafe.Pointer 是 Go 语言标准库 unsafe 包中的一个特殊类型,用于在不同类型的指针之间进行 无类型转换,允许你绕过 Go 的类型系统进行底层操作,属于“不安全”的操作。

    • 类型不兼容的指针转换(例如从 *int 转为 *float64)
    • 与 uintptr 配合操作底层内存地址
    • 修改只读字段(例如字符串的只读字节)
    • 实现类似 C 的结构体偏移访问

    unsafe.Pointer 和普通的 &T 指针(即 *T)在 Go 中有本质上的区别

    类型 说明
    *T 是类型安全的指针,指向类型 T 的数据。编译器知道它的类型信息,能自动进行内存对齐、类型检查等。
    unsafe.Pointer 是一种通用的无类型指针,可以转换为任意类型的指针或从任意类型的指针转换过来。编译器不检查其指向的类型和用法。

    package main
    
    import (
    	"fmt"
    	"unsafe"
    )
    
    func main() {
    	var x int = 100
    	// 将 *int 转换为 *float64(不安全!仅用于演示)
    	p := unsafe.Pointer(&x)
    	f := (*float64)(p) // 假装 x 是 float64
    	fmt.Println(*f)    // 输出不确定,因为解释方式不对
    }
    

    ❗这是错误用法,仅作为类型转换的演示。实际运行会出现乱码或未定义行为。

    package main
    
    import (
    	"fmt"
    	"unsafe"
    )
    
    type Person struct {
    	age   int
    	score float64
    }
    
    func main() {
    	p := Person{age: 25, score: 98.5}
    	// 获取结构体首地址
    	ptr := unsafe.Pointer(&p)
    
    	// 偏移到第二个字段(score)
    	scorePtr := (*float64)(unsafe.Pointer(uintptr(ptr) + unsafe.Offsetof(p.score)))
    	fmt.Println(*scorePtr) // 输出:98.5
    }
    

    package main
    
    import (
    	"fmt"
    	"reflect"
    	"unsafe"
    )
    
    func main() {
    	s := "hello"
    	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
    	// 强转为字节数组指针修改内容
    	b := (*[5]byte)(unsafe.Pointer(sh.Data))
    	b[0] = 'H'
    	fmt.Println(s) // 输出 "Hello"
    }
    

    ❗这是标准库明确禁止的行为,仅作教学展示。在某些平台上可能 crash!

    场景 是否安全 推荐使用
    类型间转换(*T1 ➜ *T2)
    与 uintptr 搭配偏移操作
    直接操作底层数据(如字符串修改)

    到此这篇关于Go中unsafe.Pointer类型的使用小结的文章就介绍到这了,更多相关Go unsafe.Pointer类型内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Go语言中uintptr和unsafe.Pointer的区别的实现小结
    • Go 指针、uintptr、unsafe.Pointer之间如何转换
    • Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算
    • Golang 中的 unsafe.Pointer 和 uintptr详解

    站内搜索