Go指针和unsafe.Pointer详解

1.Golang指针基础概念

  • *类型:普通指针类型,用于传递对象地址,不能进行指针运算
  • unsafe.Pointer:通用指针类型,用于转换不同类型的指针不能进行指针运算,不能读取内存存储的值(必须转换到某一类型的普通指针)。
  • uintptr:用于指针运算,GC 不把 uintptr 当指针,uintptr 无法持有对象。uintptr 类型的目标会被回收。

unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为 uintptr 进行指针运算。
unsafe.Pointer 不能参与指针运算,比如你要在某个指针地址上加上一个偏移量,Pointer是不能做这个运算的,那么谁可以呢?

就是uintptr类型了,只要将Pointer类型转换成uintptr类型,做完加减法后,转换成Pointer,通过*操作,取值,修改值,随意。

 

uintptr

  1. // uintptr 是一个整数类型,它足够大,可以存储
  2. type uintptr uintptr

unsafe.Pointer

type ArbitraryType int

type Pointer *ArbitraryType

func Sizeof(x ArbitraryType) uintptr

func Offsetof(x ArbitraryType) uintptr

func Alignof(x ArbitraryType) uintptr

unsafe.pointer用于访问操作结构体的私有变量

package main

import (
	"fmt"
	"unsafe"
)

type user struct {
	name string
	age  int
}

func main() {
	u := new(user)
	fmt.Println(*u)

	pName := (*string)(unsafe.Pointer(u))
	*pName = "张三"

	pAge := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(u)) + unsafe.Offsetof(u.age)))
	*pAge = 20

	fmt.Println(*u)
}

获取 slice 长度

  1. // runtime/slice.go
  2. type slice struct {
  3. array unsafe.Pointer // 元素指针
  4. len int // 长度
  5. cap int // 容量
  6. }
func main() {
	s := make([]int, 9, 20)
	var Len = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8)))
	fmt.Println(Len, len(s)) // 9 9
	var Cap = *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16)))
	fmt.Println(Cap, cap(s)) // 20 20
}
  1. Len: &s => pointer => uintptr => pointer => *int => int
  2. Cap: &s => pointer => uintptr => pointer => *int => int

Map结构

type hmap struct {
    count     int
    flags     uint8
    B         uint8
    noverflow uint16
    hash0     uint32
    buckets    unsafe.Pointer
    oldbuckets unsafe.Pointer
    nevacuate  uintptr
    extra *mapextra
}

和 slice 不同的是,makemap 函数返回的是 hmap 的指针,注意是指针:

  1. func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap

我们依然能通过 unsafe.Pointer 和 uintptr 进行转换,得到 hamp 字段的值,只不过,现在 count 变成二级指针了:

&mp => pointer => **int => int

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值