Go中unsafe.Pointer类型的使用小结
更新时间:2026年02月05日 09:39:49 作者:Kevin666
unsafe.Pointer 是 Go 语言标准库 unsafe 包中的一个特殊类型,用于在不同类型的指针之间进行 无类型转换,允许你绕过 Go 的类型系统进行底层操作,感兴趣的可以了解一下
unsafe.Pointer 是 Go 语言标准库 unsafe 包中的一个特殊类型,用于在不同类型的指针之间进行 无类型转换,允许你绕过 Go 的类型系统进行底层操作,属于“不安全”的操作。
🎯 使用场景
- 类型不兼容的指针转换(例如从 *int 转为 *float64)
- 与 uintptr 配合操作底层内存地址
- 修改只读字段(例如字符串的只读字节)
- 实现类似 C 的结构体偏移访问
和普通指针的区别
unsafe.Pointer 和普通的 &T 指针(即 *T)在 Go 中有本质上的区别
| 类型 | 说明 |
|---|---|
| *T | 是类型安全的指针,指向类型 T 的数据。编译器知道它的类型信息,能自动进行内存对齐、类型检查等。 |
| unsafe.Pointer | 是一种通用的无类型指针,可以转换为任意类型的指针或从任意类型的指针转换过来。编译器不检查其指向的类型和用法。 |
✅ 示例 1:不同类型指针转换
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) // 输出不确定,因为解释方式不对
}
❗这是错误用法,仅作为类型转换的演示。实际运行会出现乱码或未定义行为。
✅ 示例 2:uintptr与unsafe.Pointer配合做地址偏移(字段偏移)
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
}
✅ 示例 3:修改字符串的只读内容(危险行为)
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类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
使用Golang的singleflight防止缓存击穿的方法
这篇文章主要介绍了使用Golang的singleflight防止缓存击穿的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-04-04


最新评论