golang里面表示指针的*和&符号有什么区别? - Go中国技术社区 - golang

1,467 阅读2分钟
原文链接: gocn.vip

这是一个很基础但是用起来可以变得很复杂的问题,我单从 Go 来说一个简单例子,不参考别的什么语言。

指针,顾名思义就是指向一个变量的值,看下面这段代码:

package main

import "fmt"

func reverse(p *[]int) {
    for i, j := 0, len(*p)-1; i < len(*p)/2; i, j = i+1, j-1 {
        (*p)[i], (*p)[j] = (*p)[j], (*p)[i]
    }
}

func main() {
    v := []int{1, 2, 3, 4}
    reverse(&v)
    fmt.Println(v)
}
这段代码你可以直接运行,其效果就是反转了 v 这个切片的内容,且并没有需要 reverse 函数返回修改好的切片,这就是指针的作用之一,下面我来解释。 主要从代码第 13 行 reverse(&v) 开始看, & 操作符生成了其操作数 v 的地址,地址类型为 *[]int (一个指针类型),于是我的 reverse 函数得到了这个指针。 接着来看 reverse 函数,在 Go 里面是没有指针运算的,但通过 * 操作符可以取得指针所对应的基本值然后进行操作。所以 *p 又变成了切片类型,然后通过一个循环就反转了切面所存储值的顺序。

简单总结:

  • & 仅用于生成其操作数对应的地址,也就是用于生成指针
  • * 会出现在两个内容上:
    • 一个是类型, * Type 这样的格式代表了一个指针类型
    • 一个是指针, * Pointer 这样的格式用于获取指针所对应的基本值

最后再来看这段代码用指针的好处。当给一个函数传参时其实是会在内存空间复制一份后传递的,那么如果单纯使用切片类型传递的话,最后在 reverse 函数下处理后的切片和在 main 函数下的切片 v 是两个完全不同的,所以最后往往需要在 reverse 函数下返回处理好的切片给主函数。而像上述这种直接传递其指针,虽然也是会复制一份指针类型的变量后传递,但是却可以在 reverse 函数下通过传递过来的指针(地址)获取到原始的切片,并直接修改其内容。那么在数据内容很大的情况下就起到了节约程序开销的作用。