go unsafe包的使用

简介: 使用unsafe包修改数据

3个指针

*T

常用类型指针类型,用于传递对象地址,不能进行指针运算。

unsafe.Pointer

通用指针类型,用于转换不同类型的指针,不能进行指针运算,不能读取内存存储的值(需转换到某一类型的普通指针)

uintptr

用于指针运算,GC不把uintptr当指针,uintptr无法持有对象。uintptr

类型的目标会被回收

3者关系

unsafe.Pointer是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为uintptr进行指针运算,也就说uintptr是用来unsafe.Pointer互相配合

常用方法

unsafe.Sizeof

unsafe.Sizeof 报告传递给它的参数在内存中所占的字节长度(后面修改结构体用到)

unsafe.Offsetof()

计算成员相对于结构体的起始地址的偏移量

使用unsafe修改私有变量

//其他包引入需要Sizeof方法算出大小 偏移地址//同一个包下 直接使用Offsetof方法p :=model.Programmer{} 
fmt.Println(p)
name := (*string)(unsafe.Pointer(&p))
*name="xixi"age := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&p)) +unsafe.Sizeof(string(""))))
*age=18lan := (*string)(unsafe.Pointer(uintptr(unsafe.Pointer(&p)) +unsafe.Sizeof(string("")) +unsafe.Sizeof(int(0))))
*lan="golang"fmt.Println(p)

使用unsafe获取修改slice和map的长度

s :=make([]int, 9, 20)
Len := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) +uintptr(8)))
*Len=10//获取长度//Len := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))Cap := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) +uintptr(16)))
*Cap=10//获取容量//Cap := *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16)))fmt.Println(len(s), cap(s))
//fmt.Println(Len, Cap)

面试考点(字符串转成byte数组,会发生内存拷贝吗?)如何实现0拷贝

str :="hello world"sptr := (*reflect.StringHeader)(unsafe.Pointer(&str))
slice :=*(*[]byte)(unsafe.Pointer(sptr))
fmt.Println(slice)

总结

用unsafe包来操作内存,增加了go语言的灵活性,但同时也增加了操作风险

目录
相关文章
|
4天前
|
存储 Go 数据库
Go语言Context包源码学习
【10月更文挑战第21天】Go 语言中的 `context` 包用于在函数调用链中传递请求上下文信息,支持请求的取消、超时和截止时间管理。其核心接口 `Context` 定义了 `Deadline`、`Done`、`Err` 和 `Value` 方法,分别用于处理截止时间、取消信号、错误信息和键值对数据。包内提供了 `emptyCtx`、`cancelCtx`、`timerCtx` 和 `valueCtx` 四种实现类型,满足不同场景需求。示例代码展示了如何使用带有超时功能的上下文进行任务管理和取消。
|
1月前
|
存储 Go
Golang语言基于go module方式管理包(package)
这篇文章详细介绍了Golang语言中基于go module方式管理包(package)的方法,包括Go Modules的发展历史、go module的介绍、常用命令和操作步骤,并通过代码示例展示了如何初始化项目、引入第三方包、组织代码结构以及运行测试。
39 3
|
2月前
|
编译器 数据库连接 Go
Go Sync 包:并发的 6 个关键概念
Go Sync 包:并发的 6 个关键概念
|
2月前
|
Go 开发者
|
2月前
|
编译器 Go 开发者
|
2月前
|
缓存 Go
Go引用包版本更新但是被引用的包的子包并没有出现在vendor中的问题和解决方案
文章讨论了在Go模块项目中升级依赖包版本时遇到的子包未出现在vendor目录的问题,并提供了直接删除旧版本引用并重新执行`go mod vendor`的解决方案。
28 0
|
2月前
|
存储 SQL Go
一文弄懂Go语言的Context包,值得收藏!
在开发高效的Go应用程序时,处理超时、取消操作和传递请求范围的数据至关重要。Go标准库中的`context`包提供了一套强大的工具,用于在不同层级间传递取消信号、超时和截止时间等信息。本文首先概述了`context`包的核心功能,接着详细介绍了关键方法,如`WithCancel`、`WithDeadline`、`WithTimeout`和`WithValue`的使用场景。通过创建和派生上下文,开发者能更好地管理请求的生命周期,控制长时间运行的操作,并在并发环境中传递必要的数据。
46 1
|
3月前
|
存储 Go
go语言中fmt格式化包和内置函数汇总
【7月更文挑战第10天】本文介绍fmt包和`Errorf`用于创建格式化的错误消息。`fmt`包还涉及一些接口,如`Formatter`、`GoStringer`、`ScanState`、`Scanner`和`Stringer`,支持自定义格式化和输入/输出处理。
59 1
|
4月前
|
Go
go安装三方包并使用
go安装三方包并使用
|
4月前
|
中间件 Go
go语言后端开发学习(三)——基于validator包实现接口校验
go语言后端开发学习(三)——基于validator包实现接口校验