Golang标准库学习—unsafe

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中的三种指针:

  1. *Type : 普通指针,用于传递对象地址,不能进行指针运算。
  2. unsafe.PointerL : 通用指针类型,用于转换不同类型指针,不能进行指针运算。
  3. 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


记录每天解决的小问题,积累起来去解决大问题。 

猜你喜欢

转载自blog.csdn.net/Lazyboy_/article/details/88577860
今日推荐