Packge unsafe
import "unsafe"
unsafe包提供了一些跳过go语言类型安全限制的操作。能够访问底层内存,使用unsafe函数可以提高访问对象的速度,但是这不是go语言推荐使用的,容易出现莫名其妙的问题,不利于扩展与维护。
unsafe包中真正的代码只有五行
type ArbitraryType int type Pointer *ArbitraryType func Sizeof(x ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Alignof(x ArbitraryType) uintptr
unsafe包的用处有很多,可以通过unsafe对数组、结构体等进行操作,当然这是在某些情况下的特殊操作。
包括两个类型 :
type ArbitraryType int
ArbitraryType 是int的一个别名,但是代表一个任意GO表达式类型。
type Pointer *ArbitraryType
Pointer类型用于表示任意类型的指针。有4个特殊的只能用于Pointer类型的操作:
1. 任意类型的指针可以转换为一个Pointer类型值 2. 一个Pointer类型值可以转换为任意类型的指针 3.一个uintptr类型值可以转换为一个Pointer类型值 4. 一个Pointer类型值可以转换为一个uintptr类型值unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算。Pointer类型允许程序绕过类型系统读写任意内存。使用它时必须谨慎。
这里说一下golang中的三种指针:
- *Type : 普通指针,用于传递对象地址,不能进行指针运算。
- unsafe.PointerL : 通用指针类型,用于转换不同类型指针,不能进行指针运算。
- uintptr : 用于指针运算,无法持有对象,该类型目标会被回收。
包括三个方法:
func Sizeof(x ArbitraryType) uintptr
Sizeof返回类型x本身数据所占用的字节数。返回值是“顶层”的数据占有的字节数。例如,若x是一个切片,它会返回该切片描述符的大小,而非该切片底层引用的内存的大小。
func Offsetof(x ArbitraryType) uintptr
Offsetof返回类型x所代表的结构体字段在结构体中的偏移量,它必须为结构体类型的字段的形式。换句话说,它返回该结构起始处与该字段起始处之间的字节数。
func Alignof(x ArbitraryType) uintptr
Alignof返回类型x的对齐方式(即类型x在内存中占用的字节数);若是结构体类型的字段的形式,它会返回字段f在该结构体中的对齐方式。
示例
其实看unsafe包是因为在看golang内存对齐的事,所以这里用内存对齐示范
package main import ( "fmt" "unsafe" ) type part struct { a bool b int32 c int8 d int64 e byte } func main() { part1 := part{} fmt.Printf("bool size: %d, align: %d, offset: %d\n", unsafe.Sizeof(part1.a), unsafe.Alignof(part1.a), unsafe.Offsetof(part1.a)) fmt.Printf("int32 size: %d, align: %d, offset: %d\n", unsafe.Sizeof(part1.b), unsafe.Alignof(part1.b), unsafe.Offsetof(part1.b)) fmt.Printf("int8 size: %d, align: %d, offset: %d\n", unsafe.Sizeof(part1.c), unsafe.Alignof(part1.c), unsafe.Offsetof(part1.c)) fmt.Printf("int64 size: %d, align: %d, offset: %d\n", unsafe.Sizeof(part1.d), unsafe.Alignof(part1.d), unsafe.Offsetof(part1.d)) fmt.Printf("byte size: %d, align: %d, offset: %d\n", unsafe.Sizeof(part1.e), unsafe.Alignof(part1.e), unsafe.Offsetof(part1.e)) fmt.Printf("part1 size: %d, align: %d\n", unsafe.Sizeof(part1), unsafe.Alignof(part1)) }
从结果可以看出unsafe.Sizeof()得到的uintptr的值,unsafe.Alignof()得到的是对齐方式,unsafe.Offsetof()得到偏移值。
参考资料:
1. https://studygolang.com/pkgdoc
2. https://www.jianshu.com/p/c85fc3e31249
3. https://my.oschina.net/u/131191/blog/967908
记录每天解决的小问题,积累起来去解决大问题。