Go 指针、uintptr、unsafe.Pointer之间如何转换

 更新时间:2025年07月25日 08:24:19   作者:小许cod  
本文详细介绍了Go语言中普通指针(*T)、uintptr和unsafe.Pointer的区别与转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

普通指针(*T)

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

	a := 10
	var b *int  //int类型指针
	b = &a
	fmt.Println("a=", a)  // a=10
	fmt.Println("b=", b)  // b=0xc000225530 输出的是a的地址
	fmt.Println("c=", *b) // c=10  对a的地址进行取值

uintptr

uintptr是一个无符号的整型,它可以保存一个指针地址,它可以进行指针运算。想取值需要转成unsafe.Pointer后, 需再转到相对应的指针类型。

源代码中的定义如下。

package builtin

//uintptr is an integer type that is large enough to hold the bit pattern of any pointer.
//uintptr是一个能足够容纳指针位数大小的整数类型
type uintptr uintptr

unsafe.Pointer

unsafe.Pointer功能介绍

unsafe.Pointer定义如下,可以指向任意类型的int指针。不能进行指针运算,不能读取内存存储的值(想读取的话需要转成相对应类型的指针)。
它是桥梁,让任意类型的指针实现相互转换, 也可以转换成uintptr 进行指针运算。

type Pointer *ArbitraryType

type ArbitraryType int

unsafe.Pointer作为桥梁实现相互转换

unsafe.Pointer在unsafe包中还有以下几个函数在我们计算可能会用到

==unsafe包的几个函数==

//返回一个变量占用的内存字节数
func Sizeof(x ArbitraryType) uintptr

//返回结构体某个字段的地址相对于此结构体起始地址的偏移量
func Offsetof(x ArbitraryType) uintptr

//返回对齐系数
func Alignof(x ArbitraryType) uintptr

指针和unsafe.Pointer的转换

举些栗子:

	a := int64(100)
	var ptr *int
	ptr = (*int)(unsafe.Pointer(&a))
	fmt.Printf("%d\n", *ptr) 
	//输出100 如果是int32输出一个很大值
	

这是个将int64转换为int的场景,如果是int32的话转换起来会出问题,因为存在转换后的类型大于转换前的类型。
如果是结构体的话,我们可以用到unsafe.Offsetof函数来计算

    type People struct {
	    age    int32
	    height int64
    }
    var p = &People
	height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height))
	*((*int)(height)) = 100 //将height的值改为100
	//uintptr(unsafe.Pointer(p)) 获取了 w 的指针起始值
    //unsafe.Offsetof(w.p) 获取 b 变量的偏移量

uintptr和unsafe.Pointer的转换

同样举个栗子,结合上面的People结构体的操作,对unsafe.Pointer和uintptr的转换做一个详细的说明,对加深理解非常清晰明了。

    var p = &People
	height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height))
	*((*int)(height)) = 100 //将height的值改为100

上面的代码可以理解为以下步骤:

  1. 要想修改People结构体的height的值,首先unsafe.Pointer(p),转换为uintptr
  2. 通过unsafe.Offsetof获取height的偏移量,两者都是uintptr,可进行运算得到height的地址
  3. unsafe.Pointer将height的地址转为uintptr
  4. 先转为*int指针,然后获得height的值并赋值100

总结

指针、uintptr、unsafe.Pointer之间的转换有点绕,相信看完这个会对这个有一个非常清晰的了解。大家可以动手试试

到此这篇关于Go 指针、uintptr、unsafe.Pointer之间如何转换的文章就介绍到这了,更多相关Go 指针 uintptr unsafe.Pointer内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go同步原语Phaser和Barrier区别

    go同步原语Phaser和Barrier区别

    这篇文章主要为大家介绍了通过java讲解go同步原语Phaser和Barrier区别,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Golang中的crypto/ecdh包使用详解

    Golang中的crypto/ecdh包使用详解

    这篇文章主要给大家详细介绍了Golang 中的 crypto/ecdh 包,主要包括什么是ECDH 算法和crypto/ecdh 包的使用方法,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-09-09
  • 解决goland中编辑tpl文件不高亮没智能补全的问题

    解决goland中编辑tpl文件不高亮没智能补全的问题

    这篇文章主要介绍了解决goland中编辑tpl文件不高亮没智能补全的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Kafka安装部署+go整合过程

    Kafka安装部署+go整合过程

    go语言是一种快速、分布式、并发编程的语言,它天生适合于处理高并发场景下的消息传递和处理,在本文中,我们将介绍Kafka安装部署+go整合过程,感兴趣的朋友一起看看吧
    2024-08-08
  • GO语言开发终端命令行小工具改进更新

    GO语言开发终端命令行小工具改进更新

    这篇文章主要为大家介绍了GO语言开发终端命令行小工具的改进更新,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • victoriaMetrics库布隆过滤器初始化及使用详解

    victoriaMetrics库布隆过滤器初始化及使用详解

    这篇文章主要为大家介绍了victoriaMetrics库布隆过滤器初始化及使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Go数据结构之映射map方式

    Go数据结构之映射map方式

    这篇文章主要介绍了Go数据结构之映射map方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • Golang学习笔记(三):控制流

    Golang学习笔记(三):控制流

    这篇文章主要介绍了Golang学习笔记(三):控制流,本文讲解了IF、FOR、SWITCH、goto、break、continue等控制流语句的使用实例,需要的朋友可以参考下
    2015-05-05
  • Go 并发编程协程及调度机制详情

    Go 并发编程协程及调度机制详情

    这篇文章主要介绍了Go并发编程协程及调度机制详情,协程是Go语言最大的特色之一,goroutine的实现其实是通过协程,更多相关内容需要的朋友可以参考一下
    2022-09-09
  • Go打包静态文件的两种方式

    Go打包静态文件的两种方式

    使用 Go 开发应用的时候,有时会遇到需要读取静态资源的情况,如果不打包处理这种静态文件:发布单独挂载这种静态文件相对比较麻烦,就有人会想办法把静态资源文件打包进 Go 的程序文件中,下面介绍两种打包方式:go-bindata、go:embed,需要的朋友可以参考下
    2024-04-04

最新评论