指针
指针也是变量,用于存储变量的内存地址。
a b
156
0x1040a124 address - 0x1040a124
上面的图就说明:b变量的值时156,被存储在内存地址是0x1040a124的位置上。变量a保存着b的地址。我们就说,a指向了b
指针声明
- 格式: var a *int = 一个地址值
- 指针变量存放的是地址
- 说明:
- *int 说明指针变量类型为*int
- &b 操作符用于取一个变量的地址,例如&b表示变量b的地址
- *a 表示引用指针,也就是访问指针指向的变量a的值,例如*a表示a是地址,取a地址上的值
指针的零值
- 指针的零值是nil
a := 25
var b *int
if b == nil {
fmt.Println(b) // <nil>
b = &a
fmt.Println(b) // 0x1040a124
}
使用new函数创建指针
- size := new(int) 这样就相当于创建了一个int类型的指针,由于int类型的零值是0,所以size的零值也为0,但是size的值时指向0的地址,是0x414020
引用指针
指针不能计算,但是指针(地址)对应的值时可以计算的
b := 255
a := &b
*a++
fmt.Println(*a, a, b) // 256,0xc000014200, 256
指针作为函数参数传递
func change(val *int){
*val++
}
func main(){
a := 56
b := &a
change(b)
fmt.Println(a) // 57
}
指针所谓函数返回值
其实就是返回了一个地址出来
func hello() *int {
i := 100
return &i
}
func main() {
d := hello()
fmt.Println(*d) // 100
}
不要把数组的地址作为指针传入函数(当做函数的参数)
func modify(arr *[3]int) {
(*arr)[0] = 100
}
func main(){
arr := [3]int{1, 2, 3}
modify(&arr)
fmt.Println(arr) // [100, 2, 3]
}
- 因为其实arr[x]是(*arr)[x]的语法糖,所以可以直接用arr[x]
func modify(arr *[3]int) {
arr[0] = 100
}
func main(){
arr := [3]int{1, 2, 3}
modify(&arr)
fmt.Println(arr) // [100, 2, 3]
}
- 我们一般不建议用上面这种方式来修改,而是用切片,因为切片传入参数,虽然是值传递,但是值包含的地址,所以内部改了外部也会该
func modify(sls []int) {
sls[0] = 90
}
a := [3]int{1, 2, 3}
modify(a[:])
fmt.Println(a)
go不支持指针运算(地址是不能运算的)
值传递与指针的配合
- var a int 与 func f(a int)
- 这其实是把a的值拷贝到func中,所以没有引用关系
var a int | func f(a int)
|
a ------------|------------ a
|
|
- var a int 与 func f(pa *int)
- 调用的时候,f(&a),传入的是&a,而&a拷贝了a的地址,所以pa指向了&a的地址也就是a的地址,所以当pa改变的时候,a的地址也会改变
var a int | func f(pa *int)
|
&a <----------|--------------
↓ | |
a <-----------|------------ pa
|
|
- var cache Cache 与 func f(cache Cache)
- cache是一个对象,那么也会有引用关系
- 对象的结构,以cache为例,其实是cache内部的pData指针指向了data,那么这时候,将cache传入函数中,就是将cache拷贝一份,也就是把指针pData也拷贝了一份,那么拷贝的指针pData依旧指向data,所以当cache改变的时候,data也会改变
var cache Cache | func f(cache Cache)
|
|-----------| | |-----------|
| cache | | | cache |
| |-------| | | | |-------| |
| | pData | | | | | pData | |
| |-------| | | | |-------| |
|-----|-----| | |-----|-----|
| | |
↓ | |
data <-------|----------|
|
|
- 实例:交换两个变量的值
// 方法一:
func swap(a, b *int) {
*a, *b = *b, *a
}
a, b := 3, 4
swap(&a, &b)
fmt.Println(a, b)
// 方法二:
func swap(a, b int) (int, int) {
return b, a
}
a, b := 2, 3
a, b = swap(a, b)