定义
指针是golang中的一种数据类型,用于表示数据的内存地址。Go 提供了指针操作,但是没有指针运算。任何程序数据载入内存后,在内存都有他们的地址,可以把这个地址当做指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。
指针的意义
声明一个指针,相当于是创建了一个地址的引用,后续可以根据这个引用获取这个地址里的值。如果这个值发生变化,那么通过指针获取这个值也发生变化。
运算符
&取这个值所在的地址(对值取地址)*取这个地址里存储的值(对地址取值)
取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。
假设有个变量
i,&i表示变量i所在的内存地址,*&i表示i变量所在的内存地址里存储的值,即i变量本身。先有变量,才能取到变量所在的内存地址,所以*&可以抵消掉,但&*是不可以抵消的,因为顺序不对。
常用操作
指针地址、指针类型、指针取值
指针地址(&i)
代码在运行时,每个变量都需要存储在内存中,这个变量在内存中的位置就是指针地址。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。
取变量指针的语法:ptr := &i,其中:ptr是声明的指针变量,i是被取地址的变量。这个语句的含义是声明一个指针变量ptr,并把变量i的内存地址复制给指针变量ptr。
用一段示例代码加深理解:
func main() {
var i int = 100
ptr := &i
fmt.Printf("变量i的值是:%d,内存地址是:%p\n", i, &i)
fmt.Printf("变量ptr的值是:%p,内存地址是:%p\n", ptr, &ptr)
}
输出:
变量i的值是:100,内存地址是:0xc0000ae018
变量ptr的值是:0xc0000ae018,内存地址是:0xc0000b4018
指针类型(&i)
指针是一种数据类型,但根据值类型的不同(int、float、bool、string、array、struct),对应的指针类型分别是*int,*float,*bool……
上面代码中ptr := &i的逻辑示意图
- 变量
i的类型int,值100,内存地址0xc0000ae018 - 因为变量
ptr是用i的指针赋值,ptr的类型就为*int,值是i的内存地址0xc0000ae018,同理,作为一个变量(值),ptr也有自己的内存地址0xc0000b4018。*代表指针。
指针取值(*&i)
在对一个值使用&操作符,可以获得这个值的地址(这个变量的指针),同样的,在对一个指针使用*操作符,可以获得这个内存地址里的值,这个操作就是指针取值。
示例代码
func main() {
i := 100
j := &i // 取变量i的地址,并将指针保存到j中
fmt.Printf("j的类型是:%T\n", j)
k := *j // 指针取值
fmt.Printf("k的类型是:%T\n", k)
fmt.Printf("c的值是:%v\n", k)
}
输出
j的类型是:*int
k的类型是:int
c的值是:100
值传递和指针传递
严格地说,Golang中方法或函数只有一种传递方式,那就是值传递。每次将一个变量作为参数传递时,都会创建一个新的变量副本并将其传递给所调用的函数或方法。副本分配在不同的内存地址。 (待补充)