unsafe 库使用小结
来源:互联网 发布:js三大家族 编辑:程序博客网 时间:2024/06/05 10:52
unsafe 库让 golang 可以像 C 语言一样操作计算机内存,但这并不是 golang 推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它绕过了golang的内存安全原则,是不安全的,容易使你的程序出现莫名其妙的问题,不利于程序的扩展与维护。
unsafe 包的内容不多,下面就它提供的函数进行说明
unsafe.Alignof
获取变量的对齐值,除 int、uintptr 这些依赖CPU位数的类型,基本类型的对齐值都是固定的。 结构体的对齐值取他的成员对齐值的最大值。可以通过下面示例打印出相应的对齐值(实验机器是64位机器)。
e.g.fmt.Println(unsafe.Alignof(byte(0))) fmt.Println(unsafe.Alignof(int8(0))) fmt.Println(unsafe.Alignof(uint8(0))) fmt.Println(unsafe.Alignof(int16(0))) fmt.Println(unsafe.Alignof(uint16(0))) fmt.Println(unsafe.Alignof(int32(0))) fmt.Println(unsafe.Alignof(uint32(0))) fmt.Println(unsafe.Alignof(int64(0))) fmt.Println(unsafe.Alignof(uint64(0))) fmt.Println(unsafe.Alignof(uintptr(0))) fmt.Println(unsafe.Alignof(float32(0))) fmt.Println(unsafe.Alignof(float64(0))) //fmt.Println(unsafe.Alignof(complex(0, 0))) fmt.Println(unsafe.Alignof(complex64(0))) fmt.Println(unsafe.Alignof(complex128(0))) fmt.Println(unsafe.Alignof("")) fmt.Println(unsafe.Alignof(new(int))) fmt.Println(unsafe.Alignof(struct { f float32 ff float64 }{})) fmt.Println(unsafe.Alignof(make(chan bool, 10))) fmt.Println(unsafe.Alignof(make([]int, 10))) fmt.Println(unsafe.Alignof(make(map[string]string, 10)))
unsafe.Sizeof
查看变量所占字节数。以下面例子简要说明。
type T struct { t1 byte t2 int32 t3 int64 t4 string t5 bool}func main() { t := &T{1, 2, 3, "", true} fmt.Println(unsafe.Sizeof(*t)) fmt.Println(unsafe.Sizeof(t.t1)) fmt.Println(unsafe.Sizeof(t.t2)) fmt.Println(unsafe.Sizeof(t.t3)) fmt.Println(unsafe.Sizeof(t.t4)) fmt.Println(unsafe.Sizeof(t.t5))}
结果:
40148161
这里以0x0作为基准内存地址。打印出来总共占用40个字节。t.t1 为 char,对齐值为 1,0x0 % 1 == 0,从0x0开始,占用一个字节;t.t2 为 int32,对齐值为 4,0x4 % 4 == 0,从 0x4 开始,占用 4 个字节;t.t3 为 int64,对齐值为 8,0x8 % 8 == 0,从 0x8 开始,占用 8 个字节;t.t4 为 string,对齐值为 8,0x16 % 8 == 0,从 0x16 开始, 占用 16 个字节(string 内部实现是一个结构体,包含一个字节类型指针和一个整型的长度值);t.t5 为 bool,对齐值为 1,0x32 % 8 == 0,从 0x32 开始,占用 1 个字节。从上面分析,可以知道 t 的对齐值为 8,最后 bool 之后会补齐到 8 的倍数,故总共是 40 个字节。
unsafe.Offsetof
查看结构体成员的偏移字节数。以上面这个例子中结构体 T 为例。
func main() { t := &T{1, 2, 3, "", true} fmt.Println(unsafe.Offsetof(t.t1)) fmt.Println(unsafe.Offsetof(t.t2)) fmt.Println(unsafe.Offsetof(t.t3)) fmt.Println(unsafe.Offsetof(t.t4)) fmt.Println(unsafe.Offsetof(t.t5))}
结果
0481632
分析如上 unsafe.Sizeof 中说明。
unsafe.Pointer
这个主要用于不同指针类型之间进行强制类型转换。它是一个中介者,不同指针类型不能直接进行转换,只能通过它中转一下。但是它还无法直接进行指针运算,必须将其转化成 uintptr 类型才能进行指针的运算,uintptr 与 unsafe.Pointer 之间可以相互转换。
这里仍然取上面定义的结构体 T 进行说明。
t := &T{1, 2, 3, "this is a example", true} ptr := unsafe.Pointer(t) t1 := (*byte)(ptr) *t1 = 4 t2 := (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + unsafe.Offsetof(t.t2))) *t2 = 99 fmt.Println(t) t3 := (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + unsafe.Offsetof(t.t3))) *t3 = 333 fmt.Println(t)
借助于 unsafe.Pointer,我们实现了像 C 语言中的指针偏移操作。可以看出,这种不安全的操作使得我们可以在任何地方直接访问结构体中未公开的成员,只要能得到这个结构体变量的地址。
- unsafe 库使用小结
- Unsafe 使用
- 关于使用Unsafe code
- unsafe的使用
- Unsafe 基本使用
- unity使用unsafe注意事项
- 使用sun.misc.Unsafe
- sun.misc.Unsafe类 学习小结
- Unsafe
- Unsafe
- Unsafe
- C#中unsafe的使用
- C#中unsafe的使用
- C#中unsafe的使用
- unsafe的使用报错
- Unsafe--Java为什么会引入及如何使用Unsafe
- sync 库使用小结
- reflect 库使用小结
- eclipse快捷键
- LeetCode(228) Summary Ranges
- 使用的主要开源技术
- 成熟是什么
- 对 Linux 初级、中级、高级用户非常有用的 60 个命令
- unsafe 库使用小结
- 工厂模式
- JavaEE_JavaScript__前台(Jsp页面) + 后台数据处理(Servlet),与javaScript的过程的处理
- JScrollPane控件中添加其他控件的问题&&JScrollPane设置滚动条&&调整滚动速度
- VC++向txt文件中写入字符串
- 动态网站开发技术学习3:ASP.NET内置对象之Response对象
- 重装mysql安装最后一项的apply security settings 总是不能进行。提示error nr.1045然后就是access denied for user 'root' @'loca
- Eclipse快捷键大全
- android volley problem