unsafe.Pointer其实就是类似C的void *,在golang中是用于各种指针相互转换的桥梁。uintptr是golang的内置类型,是能存储指针的整型,uintptr的底层类型是int,它和unsafe.Pointer可相互转换。uintptr和unsafe.Pointer的区别就是:unsafe.Pointer只是单纯的通用指针类型,用于转换不同类型指针,它不可以参与指针运算;而uintptr是用于指针运算的,GC 不把 uintptr 当指针,也就是说 uintptr 无法持有对象,uintptr类型的目标会被回收。golang的unsafe包很强大,基本上很少会去用它。它可以像C一样去操作内存,但由于golang不支持直接进行指针运算,所以用起来稍显麻烦。

利用unsafe.Pointer来突破私有成员

package p

import (     "fmt" ) type V struct {

i int32     j int64

}

func (this V) PutI() {

fmt.Printf("i=%d\n", this.i)

}

func (this V) PutJ() {

fmt.Printf("j=%d\n", this.j)

}

通过unsafe包来实现对V的成员i和j赋值,然后通过PutI()和PutJ()来打印观察输出结果

package main

import (     "poit/p"     "unsafe" )

func main() {

var v *p.V = new(p.V)

var i *int32 = (*int32)(unsafe.Pointer(v))

*i = int32(98)

var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int32(0)))))

*j = int64(763)

v.PutI()

v.PutJ() }

核心思想就是:结构体的成员在内存中的分配是一段连续的内存,结构体中第一个成员的地址就是这个结构体的地址,您也可以认为是相对于这个结构体偏移了0。相同的,这个结构体中的任一成员都可以相对于这个结构体的偏移来计算出它在内存中的绝对地址。

具体来讲解下main方法的实现:

var v *p.V = new(p.V)

new是golang的内置方法,用来分配一段内存(会按类型的零值来清零),并返回一个指针。所以v就是类型为p.V的一个指针。

var i *int32 = (*int32)(unsafe.Pointer(v))

将指针v转成通用指针,再转成int32指针。这里就看到了unsafe.Pointer的作用了,您不能直接将v转成int32类型的指针,那样将会panic。刚才说了v的地址其实就是它的第一个成员的地址,所以这个i就很显然指向了v的成员i,通过给i赋值就相当于给v.i赋值了,但是别忘了i只是个指针,要赋值得解引用。

*i = int32(98)

现在已经成功的改变了v的私有成员i的值

uintptr和unsafe.Pointer的区别相关推荐

  1. Golang unsafe.Pointer指针

    相较于 C 而言,Go 语言在设计时为了使用安全给指针在类型和运算上增加了限制,这让Go程序员既可以享受指针带来的便利,又避免了指针的危险性.除了常规的指针外,Go 语言在 unsafe 包里其实还通 ...

  2. go uintptr unsafe Pointer offset() 的使用

    go语言基本类型 类型名称 有无符号 占用位数 int8 Yes 8 int16 Yes 16 int32 Yes 32 int64 yes 64 uint8 No 8 uint16 No 16 ui ...

  3. Go unsafe Pointer

    Go unsafe Pointer Go被设计为一种强类型的静态语言,强类型意味着类型一旦确定就无法更改,静态意味着类型检查在运行前就做了. 指针类型转换 为了安全考虑,两个不同类型的指针不能相互转换 ...

  4. Go 指针 unsafe.Pointer

    Go语言是个强类型语言.也就是说Go对类型要求严格,不同类型不能进行赋值操作.指针也是具有明确类型的对象,进行严格类型检查.下面的代码会产生编译错误 : package main import (&q ...

  5. cursor:hand 与 cursor:pointer的区别介绍

    都是手型的光标,但是还是有一丢丢的区别. cursor:hand  IE完全支持,但是在Firefox是不支持的,木有效果. cursor:pointer 是CSS2.0的标准,所以Firefox是支 ...

  6. cursor:hand与cursor:pointer的区别介绍

    cursor:hand 与 cursor:pointer 的效果是一样的,都像光标指向链接一样,光标变成手行. cursor:hand :IE完全支持.但是在firefox是不支持的,没有效果. cu ...

  7. Go 学习笔记(74)— Go 标准库之 unsafe

    Go 语言自带的 unsafe 包的高级用法, 顾名思义,unsafe 是不安全的.Go 将其定义为这个包名,也是为了让我们尽可能地不使用它.不过虽然不安全,它也有优势,那就是可以绕过 Go 的内存安 ...

  8. golang byte转string_golang面试题:怎么避免内存逃逸?

    问题 怎么避免内存逃逸? 怎么答 在runtime/stubs.go:133有个函数叫noescape.noescape可以在逃逸分析中隐藏一个指针.让这个指针在逃逸分析中不会被检测为逃逸. // n ...

  9. golang后端面试题总结

    什么是goroutine? Goroutine是Go语言中的轻量级线程,可以轻松地实现并发编程.Goroutine的调度是由Go语言运行时(runtime)进行管理的,可以自动地在多个线程之间分配任务 ...

最新文章

  1. 工作流-----WorkFlow
  2. 超越百度的口罩检测算法
  3. 成功:选择比努力更重要,智慧比勤奋更重要
  4. 运动后肌肉酸痛怎么办?
  5. C++标准转换运算符:dynamic_cast
  6. keil安装及mdk
  7. java毕业设计小小银动漫网站源码+lw文档+mybatis+系统+mysql数据库+调试
  8. java生成api文档工具_api文档自动生成工具
  9. https://www.i5seo.com/
  10. React学习笔记—简易信息管理,实现CUD
  11. 强化学习 - Deep RL开源项目总结
  12. Let‘s Go Rust 系列之定时器 Ticker Timer
  13. 使用ccache大幅度加速gcc编译速度
  14. 一个完整推荐系统的设计实现
  15. html+css 动画制作简单的渐变效果(图片视频)
  16. vue 解决: target is not existed: .page-component__scroll .el-scrollbar__wrap“问题
  17. python程序sum函数的用法_python 运行sum函数的使用
  18. OllyDbg 官网及下载地址
  19. 从程序员辞职到知乎上市,你还以为周源的成功是偶然吗?
  20. 实用项目管理之制定项目章程

热门文章

  1. 教你怎么用Iebook超级精灵去赚钱
  2. C/C++编程学习 - 第4周 ⑧ 小蒜蒜的成绩
  3. 软件工程的四项基本原则
  4. 华资软件Java开发实习生——2021届暑期实习生面经(OC)
  5. 合肥工业大学计算机与信息学院研究生,合肥工业大学计算机与信息学院硕士生导师介绍:唐益明...
  6. 在日常办公中如何正确使用计算机,日常办公中的节能降耗小知识
  7. 获取当前位置附近的小吃店功能
  8. 新浪微博id的62进制转换
  9. unity实验-模拟太阳系星体运动
  10. JisonLexerError: Lexical error on line 1: Unrecognized text Erroneous area:\n1: 100VH - 44px