微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

原文地址:https://www.jb51.cc/wenti/3285150.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐