unsafe 库使用小结

2024-08-30 04:32
文章标签 使用 小结 unsafe

本文主要是介绍unsafe 库使用小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

unsafe 库让 golang 可以像 C 语言一样操作计算机内存,但这并不是 golang 推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它绕过了golang的内存安全原则,是不安全的,容易使你的程序出现莫名其妙的问题,不利于程序的扩展与维护。

unsafe 包的内容不多,下面就它提供的函数进行说明

unsafe.Alignof

获取变量的对齐值,除 int、uintptr 这些依赖CPU位数的类型,基本类型的对齐值都是固定的。 结构体的对齐值取他的成员对齐值的最大值。可以通过下面示例打印出相应的对齐值(实验机器是64位机器)。

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  float32ff 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)))
类型对齐值
byte1
bool1
int81
uint81
int324
int648
uint324
uint648
uintptr8
float328
float648
complex648
complex1288
chan8
slice8
map8
structit depends on the max align among its members

##unsafe.Sizeof
查看变量所占字节数。以下面例子简要说明。

type T struct {t1 bytet2 int32t3 int64t4 stringt5 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))
}

结果:

40
1
4
8
16
1

这里以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))
}

结果

0
4
8
16
32

分析如上 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 = 4t2 := (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + unsafe.Offsetof(t.t2)))*t2 = 99fmt.Println(t)t3 := (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) + unsafe.Offsetof(t.t3)))*t3 = 333fmt.Println(t)

借助于 unsafe.Pointer,我们实现了像 C 语言中的指针偏移操作。可以看出,这种不安全的操作使得我们可以在任何地方直接访问结构体中未公开的成员,只要能得到这个结构体变量的地址。

这篇关于unsafe 库使用小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1119805

相关文章

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删