golang 利用指针导出变量
来源:互联网 发布:韩语电影字幕翻译软件 编辑:程序博客网 时间:2024/05/15 13:40
golang 利用指针导出变量
1 golang中的指针类型:unsafe.Pointer & uintptr
unsafe.Pointer
类似 C
的 void *
,在golang中是用于各种指针相互转换的桥梁。uintptr
是golang的内置类型,能存储指针的整型,uintptr
的底层类型是 int
,和 unsafe.Pointer
可相互转换。
unsafe.Pointer
用于转换不同类型指针,不可以参与指针运算uintptr
用于指针运算,GC会自动回收uintptr
类型的目标
Go语言是强类型语言,指针也是具有明确类型的对象,进行严格类型检查,因此下面的代码会产生编译错误
package mainimport ( "fmt")func main() { u := uint32(32) i := int32(1) fmt.Println(&u, &i) // 打印出地址 p := &i // p 的类型是 *int32 p = &u // &u 的类型是 *uint32,与 p 类型不同,不能赋值 p = (*int32)(&u) // 同样无效 fmt.Println(p)}
unsafe
包提供的 Pointer
方法可以实现
package mainimport ( "fmt" "unsafe")func main() { u := uint32(32) i := int32(1) fmt.Println(&u, &i) p := &i p = (*int32)(&u) p = (*int32)(unsafe.Pointer(&u)) fmt.Println(p)}
2 利用 unsafe.Pointer 突破私有成员
package mainimport ( "fmt" "text/template" "unsafe")// MyTemplate 定义和 template.Template 只是形似type MyTemplate struct { name string parseTree *unsafe.Pointer common *unsafe.Pointer leftDelim string rightDelim string}func main() { t := template.New("Foo") p := (*MyTemplate)(unsafe.Pointer(t)) p.name = "Bar" // 关键在这里,突破私有成员 fmt.Println(p, t)}
输出结果
&{Bar <nil> <nil> } &{Bar <nil> <nil> }
t.name
也变成 Bar
, 成功突破 template.Template
私有字段 name
3 指针运算
首先定义结构V
type V struct { i int32 j int64}
指针运算
package mainimport ( "poit/p" "unsafe")func main() { var v *p.V = new(p.V) // 分配一段内存并返回一个指针,v是类型为p.V的一个指针 var i *int32 = (*int32)(unsafe.Pointer(v)) // 将指针v转成通用指针,再转成int32指针,不能直接将v转成int32类型的指针 *i = int32(98) // 改变v的私有成员i的值 var j *int64 = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + uintptr(unsafe.Sizeof(int32(0))))) // 得到v.j在内存中的地址,unsafe.Sizeof得到一个值占用的字节空间 *j = int64(763) // 改变v的私有成员j的值}
4 地址对齐
type W struct { b byte // 1 i int32 // 4 j int64 // 8}func init() { var w *W = new(W) fmt.Printf("size=%d\n", unsafe.Sizeof(*w)) // size=16}
输出 size=16
而非 size=13
,发生了对齐。struct中的对齐值是它成员中的最大对齐值。每个成员类型都有对齐值,可以用 unsafe.Alignof
方法来计算,如 unsafe.Alignof(w.b)
可以得到b在w中的对齐值。在b和i中间有3个填充,size=13+3=16
通过unsafe取值
package mainimport ( "fmt" "unsafe")func main() { var b []byte = []byte{'a', 'b', 'c'} var c *byte = &b[0] fmt.Println(*(*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + uintptr(1))))}
阅读全文
0 0
- golang 利用指针导出变量
- Golang初级系列教程-内存变量指针
- 利用指针实现变量交换
- golang变量
- golang指针
- golang指针
- 利用指针访问局部静态变量
- 利用指针修改静态变量的值
- golang 变量生成周期
- golang声明变量
- golang 变量声明
- Golang 指针的坑
- golang 空指针
- 变量,指针,指针变量
- 利用指针获取私有成员变量的值
- golang变量作用域问题
- 学习Golang语言(2): 变量
- 跟着猫哥学Golang[2] - 变量
- 从国企到阿里的面试经历(二)
- 欢迎使用CSDN-markdown编辑器
- kafka学习-环境搭建
- Java并发 基础 二
- UDP_server服务器和用户空间下如何实现可靠性
- golang 利用指针导出变量
- SpringBoot入门之HelloWorld
- 语音识别综述 awesome-speech-recognition-speech-synthesis-papers
- 利用Fragment实现应用的主布局
- hmac_SHA256加密
- 《三体》之"地球往事"读后感
- c++存储区域
- MySQL安装相关
- ntpdate 同步时间