文档章节

GoLang 强制类型转换:unsafe.Pointer

喻恒春
 喻恒春
发布于 2013/04/13 15:18
字数 383
阅读 11070
收藏 12

注意此种转换只适合简单类型,对于有对象描述的类型是完全不适用的,鸡肋啊

更详细的文章请参见@陈一回 http://my.oschina.net/goal/blog/193698

ps:补充另外一种用法,这次就不鸡肋了

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

package main

import (
	"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 main

import (
	"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)
}


补充:实际使用中unsafe可用场景很少,稍微复杂一点的结构,比如struct,unsafe根本不能适用,正确的方法还是要靠 type assertion

ps:发现一种用法,看代码

package main

import (
	"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


© 著作权归作者所有

共有 人打赏支持
喻恒春

喻恒春

粉丝 106
博文 29
码字总数 21951
作品 5
郑州
程序员
加载中

评论(2)

smart_w
smart_w
突破私有变量很不错
一曲
一曲
不错,学习!
golang: 利用unsafe操作未导出变量

看了 @喻恒春 大神的利用unsafe.Pointer来突破私有成员,觉得例子举得不太好。而且不应该简单的放个demo,至少要讲一下其中的原理,让看的童鞋明白所以然。see:http://my.oschina.net/achun...

陈亦
2014/01/17
0
10
Go之unsafe.Pointer && uintptr类型

Go之unsafe.Pointer && uintptr类型 unsafe.Pointer 这个类型比较重要,它是实现定位欲读写的内存的基础。官方文档对该类型有四个重要描述: 大多数指针类型会写成T,表示是“一个指向T类型变...

秋风醉了
2016/08/08
184
0
【go语言】wait,why not safe

slice?俺知道,不就是基于数组的一个视窗嘛! 出个题呗~ 好~ package main func main() { var arr = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} s := arr[2:6] modify(s) } func modify(tmp []......

qingkechina
2017/02/07
0
0
cgo的一些经验

cgo可以在go语言中夹杂着C函数或数据,在使用cgo时,有一些需要注意的: 1、go中的int/int32/int64/uint32/uint64和C语言中的int/int32等是不同的,因此,C语言的函数的参数不能是go语言的i...

徐学良
2015/12/25
67
0
Golang 源码阅读 os.File

最近写程序过程感觉golang读写文件比较慢。因此决定读一下源码。 src/os/file.go http://www.ieyebrain.com:8080/golang/src/os/file.go 中定义了file的函数: Name, Read,Write,Seek,Close等...

shengjuntu
2016/11/13
39
0

没有更多内容

加载失败,请刷新页面

加载更多

Java Web--增删改查之二界面后台java代码(转载参考)

/** *  *//** * @author Administrator * */package dao; import java.sql.*;public class DBConn {/** * 链接数据库 * @return */  ...

小橙子的曼曼
9分钟前
0
0
Redis源码阅读笔记-对象及其类型和编码

总结之《Redis设计与实现》 对象 Redis中是使用对象来便是数据库中的键和值。 结构 // server.h...#define LRU_BITS 24...typedef struct redisObject { unsigned type:4; ...

Jian_Ming
22分钟前
0
0
laravel框架常用目录路径

laravel框架常用目录路径 app_path()app_path函数返回app目录的绝对路径:$path = app_path();你还可以使用app_path函数为相对于app目录的给定文件生成绝对路径:$path = app_p...

高处胜寒
23分钟前
0
0
记一次winserver2003系统,https无法访问,内存占用持续增加,解决办法

先交代一下环境: win server2003系统,系统装在hyper-v虚拟机里 大概2016年底的镜像,距离今天两年左右 病症:大概9月10号左右用这个镜像还可以访问https,但是今天用这个镜像新装的系统,就...

阳阳露
38分钟前
3
0
Vue学习资料

一直以为Vue是依赖nodejs的。 作为前端也可以耦合性就很低了。 //npm包管理器 进行管理npm install vue//初始化一个项目vue init//本地调试npm run dev//编译完成 ...

大灰狼wow
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部