Golang 中的 unsafe 包详解

Golang 中的 unsafe 包用于在运行时进行低级别的操作。这些操作通常是不安全的,因为可以打破 Golang 的类型安全性和内存安全性,使用 unsafe 包的程序可能会影响可移植性和兼容性。接下来看下 unsafe 包中的类型和函数。

unsafe.Pointer 类型

通常用于类型转换和指针运算,定义如下:

复制代码
type Pointer *ArbitraryType

可以将其他类型的指针转换为unsafe.Pointer类型,以进行低级别的操作。看个简单示例:

复制代码
package main
 
import (
	"fmt"
	"unsafe"
)
 
func main() {
	i := 30
	ptr1 := &i
 
	var ptr2 *int64 = (*int64)(unsafe.Pointer(ptr1))
	*ptr2 = 8
 
	fmt.Println(i)
}

unsafe.ArbitraryType 类型

定义如下:

复制代码
type ArbitraryType int

ArbitraryType 仅用于文档目的,实际上并不是 unsafe 包的一部分,用于表示任意 Go 表达式的类型。

unsafe.IntegerType 类型

定义如下:

复制代码
type IntegerType int

IntegerType 仅用于文档目的,实际上并不是 unsafe 包的一部分,用于表示任意整数类型。

unsafe.Add 函数

定义如下:

复制代码
func Add(ptr Pointer, len IntegerType) Pointer

用于进行指针的加法运算,将一个指针和指定的偏移量相加,得到一个新的指针。简单示例如下:

复制代码
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	arr := []int{1, 2, 3, 4}
	index := 2
	ptr := unsafe.Pointer(&arr[0])
	newPtr := unsafe.Add(ptr, uintptr(index)*unsafe.Sizeof(arr[0]))
	cc := (*int)(newPtr)
	fmt.Println(*cc)
	fmt.Println(newPtr)
}

unsafe.Sizeof 函数

定义如下:

复制代码
func Sizeof(x ArbitraryType) uintptr

用于获取一个类型或值的字节大小。简单示例如下:

复制代码
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var arr [5]int
	fmt.Println(unsafe.Sizeof(arr)) // 输出: 40
	fmt.Println(unsafe.Sizeof(0))   // 输出: 8
}

unsafe.Slice 函数

定义如下:

复制代码
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType

用于创建一个与原始数组共享底层数据的切片。简单示例如下:

复制代码
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var arr [5]int
	arr[0] = 10
	arr[1] = 20
	arr[2] = 30
	arr[3] = 40
	arr[4] = 50

	slice := unsafe.Slice(&arr[0], 3)
	fmt.Println(slice) // 输出: [10 20 30]
}

定义了一个包含5个整数的数组 arr,然后使用 unsafe.Slice 函数创建了一个从索引0开始、长度为3的切片 slice。

unsafe.Offsetof

定义如下:

复制代码
func Offsetof(x ArbitraryType) uintptr

作用是返回结构体成员在内存中的位置离结构体起始处(结构体的第一个字段的偏移量都是0)的字节数。简单示例如下:

复制代码
package main

import (
	"fmt"
	"unsafe"
)

type MyStruct struct {
	Field1 int64
	Field2 string
}

func main() {
	var myStruct MyStruct
	fmt.Println(unsafe.Offsetof(myStruct.Field1)) // 输出: 0
	fmt.Println(unsafe.Offsetof(myStruct.Field2)) // 输出: 8
}

unsafe.Alignof

定义如下:

复制代码
func Alignof(x ArbitraryType) uintptr

返回参数对齐所需的字节数。对于某些结构体,其字段的内存对齐可能会影响到结构体所占用的内存大小。简单示例如下:

复制代码
package main

import (
	"fmt"
	"unsafe"
)

type MyStruct struct {
	Field1 int
	Field2 string
}

func main() {
	fmt.Println(unsafe.Alignof(int(0)))     // 输出: 8
	fmt.Println(unsafe.Alignof(string(""))) // 输出: 8
	fmt.Println(unsafe.Alignof(MyStruct{})) // 输出: 8
}

小结

unsafe 包提供了一些低级别的操作,使用的时候一定要谨慎,必须非常了解自己在做什么,以免引入不安全的问题。

相关推荐
OPEN-F3 分钟前
Python进阶教程:装饰器与生成器深入
开发语言·python
Zane19944 分钟前
HashMap 为什么要在长度16、容量必须是2的幂这些细节上较劲
java·后端
掘金者阿豪33 分钟前
若依启动突然报 Redis MISCONF?一次从应用报错到磁盘爆满的完整排查记录
后端
千里码aicood1 小时前
基于Python的电商数据采集系统(大数据+爬虫)
开发语言·python
boooooooom1 小时前
尝尝咸淡:从朴素 RAG 到 Graph RAG——一个烹饪问答系统的三层检索升级之路
前端·后端·llm
陈皮波比茶2 小时前
Python项目实战-网络机器人(爬虫)
开发语言·网络·爬虫·python·机器人
JavaPub-rodert2 小时前
Go 后台如何同时兼容 MySQL、PostgreSQL、SQLite 和 SQL Server?从 ShiyuAdmin 看 GORM 多数据库适配
数据库·mysql·postgresql·golang·javapub·王仕宇
2601_963870183 小时前
【计算机毕业设计】基于Vue+Spring Boot的助农电商系统的设计与实现
spring boot·后端·课程设计
法哥20123 小时前
用 C++ 控制 CMW100,到底在干什么?
开发语言·c++
sun༒3 小时前
Spring @Scheduled 定时任务详解:Cron表达式、执行顺序、优先级与并行调度
java·后端·spring