Go学习——6.指针

指针

指针也是变量,用于存储变量的内存地址。

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值