⭐在go里面使用unsafe标准库
使用了unsafe包,该代码可能会绕过Go语言的类型安全检查,因此在实际开发中应该谨慎使用
Alignof
获取指定类型的对齐方式。对齐方式指的是编译器在分配内存时,将数据类型存储在内存中的起始地址的对齐方式
函数原型
func Alignof(variableType T) uintptr
其中,variableType是需要获取对齐方式的类型,可以是一个基本类型,也可以是一个结构体或数组等自定义类型。uintptr是一个无符号整数类型,可以用来表示指针或内存地址的整数值
Alignof函数返回的是指定类型的对齐方式,以字节为单位。例如,对于一个64位整数类型int64,通常的对齐方式为8字节(64位),因此调用Alignof(int64)会返回8
示例代码
var i int
var f float64
var s string
var m map[string]string
fmt.Printf("int size %d\n", unsafe.Alignof(i))
fmt.Printf("float64 size %d\n", unsafe.Alignof(f))
fmt.Printf("string size %d\n", unsafe.Alignof(s))
fmt.Printf("map size %d\n", unsafe.Alignof(m))
输出
int size 8
float64 size 8
string size 8
map size 8
Sizeof
获取变量大小
函数原型
func Sizeof(x ArbitraryType) uintptr
示例代码
var i int
var f float64
var s string
var a []int
var m map[string]string
fmt.Printf("int size %d\n", unsafe.Sizeof(i))
fmt.Printf("float64 size %d\n", unsafe.Sizeof(f))
fmt.Printf("string size %d\n", unsafe.Sizeof(s))
fmt.Printf("array size %d\n", unsafe.Sizeof(a))
fmt.Printf("map size %d\n", unsafe.Sizeof(m))
输出
int size 8
float64 size 8
string size 16
array size 24
map size 8
Offsetof
unsafe.Offsetof函数可以获取指定结构体成员变量的偏移量(offset)。偏移量指的是该成员变量相对于结构体起始地址的偏移量,以字节为单位
函数原型
func Offsetof(x ArbitraryType) uintptr
示例代码
- 获取一个不存在的struct属性会报错 ``` type Person struct { name string age int }
p := Person{“John Doe”, 30}
fmt.Printf(“%d\n”, unsafe.Offsetof(p.name))
fmt.Printf(“%d\n”, unsafe.Offsetof(p.age))
输出
0 16
---
**[]byte类型的切片转换string类型**
代码示例
var bs = []byte{‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ‘,’, ‘ ‘, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’, ‘!’}
sr := (string)(unsafe.Pointer(&bs))
fmt.Printf(“%s\n”, sr);
跟(string)转换变量效果类似
输出
hello, world!
---
**获取StringHeader**
StringHeader 用于描述字符串的底层实现
代码示例
var foo = “hello world!”
header := (*reflect.StringHeader)(unsafe.Pointer(&foo))
fmt.Printf(“len %d\n”, header.Len)
fmt.Printf(“ptr %x\n”, header.Data)
输出
len 12 ptr 10a98cf
---
**获取SliceHeader**
SliceHeader是Go语言标准库unsafe中的一个结构体类型,用于描述切片的底层实现
代码示例
var nations = []string{“China”, “Japan”, “Canada”, “Italy”}
header := (*reflect.SliceHeader)(unsafe.Pointer(&nations))
fmt.Printf(“len %d\n”, header.Len) fmt.Printf(“cap %d\n”, header.Cap) fmt.Printf(“ptr %x\n”, header.Data)
输出
len 4 cap 4 ptr c000064f30
---
**通过指针遍历切片**
代码示例
var bs = []byte{‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ‘,’, ‘ ‘, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’, ‘!’}
ptr := unsafe.Pointer(&bs[0])
header := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
offset := 0
for offset < header.Len { next := (*byte)(ptr)
fmt.Println(string(*next))
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(bs[offset]))
offset++ } ```
输出
hello, world!