golang 标准库 之 unsafe

737 阅读2分钟
青春因磨砺而出彩,人生因奋斗而升华

unsafe: 

unsafe: 用于go编译器,在编译阶段使用。是不安全的,可以绕过Go语言的类型系统,直接操作内存。unsafe可以直接读写内存;

Pointer类型: 

unsafe.Pointer: 是实现定位与读写的内存的基础,可以指向任意类型,是各种类型指针转换的桥梁; 

1. 任何类型的指针都可以转化为unsafe.Pointer 

2. unsafe.Pointer可以被转化为任和类型的指针值 

3. uintptr可以被转化为unsafe.Pointer 

4. unsafe.Pointer可以被转化为uintptr  

uintptr: golang的内置类型,是能存储指针的整形,用于指针运算, gc不把uintptr当作指针,uintptr无法持有对象。uintptr类型的目标会被回收 

 unsafe.Pointer和uintptr的区别:

 1. unsafe.Pointer: 只是单纯的通用指针类型,用于转换不同类型指针,不可以参与指针运算 

2. uintptr: 用于指针运算,GC不把uintpitr当指针,即uintpitr无法持有对象,uintptr类型的目标会被回收

h := "abc"                                          
fmt.Printf("h: type: %T, value: %v\n", h, h)        

// 1.将 h 转化为通用指针(unsafe.Pointer)类型                                      
p := unsafe.Pointer(&h)                             
fmt.Printf("p-->type: %T, value: %v\n", p, p) 

// 2.将通用指针(unsafe.Pointer)转化为字符串型指针                                   
pb := (*string)(p)                                  
fmt.Printf("pb-->type: %T, value: %v\n", pb, pb)   

// 3.将unsafe.Poniter转换为 uintptr                                       
up0 := uintptr(p)                                   
fmt.Printf("up0-->type: %T, value: %v\n", up0, up0) 

// 4.将uintptr类型转换为 unsafe.Pointer类型
up1 := unsafe.Pointer(up0)                          
fmt.Printf("up1-->type: %T, value: %v\n", up1, up1) 

// 5.给转化后的字符串赋值                                       
*pb = "why"                                         
fmt.Printf("h: %v, pb: %v", h, *pb) 

Sizeof:

unsafe.Sizeof(v ArbitraryType) uintptr 

介绍:返回变量v占用的内存空间的字节数,该字节数不是按照变量v实际占用的内存计算,这个大小只与类型有关;如:int8占用一个字节

Offsetof

unsafe.Offsetof(v ArbitraryType) uintptr

 介绍: 返回由v所指示的某结构体中的字段在该结构体中的位置偏移字节数,注意:v表达式必须是"struct.filed"形式。

type testOfs struct {                   
	t0 byte                           
	t1 int                            
	t2 string                         
	t3 int                            
}                                     
var ts testOfs                           
fmt.Println(unsafe.Offsetof(ts.t0)) // 0   
fmt.Println(unsafe.Offsetof(ts.t1)) // 8
fmt.Println(unsafe.Offsetof(ts.t2)) // 16
fmt.Println(unsafe.Offsetof(ts.t3)) //	32