1. 概念
我们看看go是怎么定义指针的:
大意是:指针类型表示指向给定类型变量的所有指针集,称为指针的基类型。未初始化指针的值为零。
官方这段解释,说了等于没说。指针到底是什么,今天来搞明白他。实话是说,刚开始了解到指针的时候,内心是恐惧的,有一部分原因是很多人把指针给神话了。
下面我们来举一个例子,让大家理解指针。
1、 同其他类型一样,指针也是一个类型。
string 是一个类型,int是一个类型,pointer也是一个类型。
2、string支持的运算有:+, int支持的运算有+ - * /
指针支持的运算有:* 取值
3、*string *int *byte 都是指针一种类型,类似于[]int 表示一个int数组,[]string 表示一个string数组。 另外,这里的* 和上面的取值是不同的涵义,这里是表示类型定义,而上面2中表示的操作符号。
我们来举一个例子吧:
风筝的把手为啥可以控制风筝?因为把手通过一根线连在了风筝上面。同理,指针变量为啥可以控制普通变量,因为他里面存的是普通变量的地址。通过这个地址,可以对地址上面的值做修改。
2. 基本操作
go语言中,如果不通过unsafe包,则对于指针的操作相对简单,请看下举例和注释
func main() {
//
var AA string
AA = "风筝"
//把手
var BB *string
//用一跟线,将风筝链接到把手上; &取地址,
BB = &AA
//打印BB的值,也就是AA的地址
fmt.Println("BB= ", BB)
//通过BB中存的值(AA的地址取值),也就是通过AA的地址取AA的值
fmt.Println("*BB= ", *BB)
//验证一下 AA的地址是不是 = BB的值
fmt.Println("&AA= ", &AA)
}
//BB= 0xc000040240
//*BB= 风筝
//&AA= 0xc000040240
3. unsafe高级用法及转换
通过指针的加减运算,对地址所在的值做修改。
func main() {
var pv = new(v)
var i = (*int32)(unsafe.Pointer(pv))
*i = 100
fmt.Println("pv.i: ", pv.i)
//
var j = (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(pv)) + 4))
*j = 123
fmt.Println("pv.j: ", pv.j)
}
unsafe.Pointer(uintptr(unsafe.Pointer(pv)) 获取到结构体的初始位置,也就是第一个元素的位置。
+ 4表示加四个字节的位置,就会偏移到j的地址。
unsafe.Pointer: 表示通用指针类型,任何指针类型都可以转换为unsafe.Pointer
uintptr: 表示一个指针地址,通过unsafe.Pointer转换而来,可以进行加减运算
今天就先到这里吧,后面有时间聊聊逃逸分析吧
\