当我们调用一个带有参数的函数是,参数是原值的拷贝:

func zero(x int) {
  x = 0
}
func main() {
  x := 5
  zero(x)
  fmt.Println(x) // x is still 5
}

上面这段代码中,zero() 函数不会改变主函数中 x 的原值。但如果我们想要这样做呢?一种实现办法是使用一种称为指针的特殊数据类型。

func zero(xPtr *int) {
  *xPtr = 0
}
func main() {
  x := 5
  zero(&x)
  fmt.Println(x) // x is 0
}

指针指向的是内存中 值的存储地址,而不是值本身。通过使用指针 *int, zero() 函数能够修改原始变量。

The * and & operators

在 Go 中,指针由 * 字符和存储值的类型表示。在 zero() 函数中,xPtr 是指向 int 类型的指针。

*也用于指针变量的解引用,这使得我们可以访问指针指向的值。当我们写 *xPtr = 0 时,我们在说“将整形 0 存储在 xPtr 指向的内存位置”。如果我们尝试执行 xPtr = 0,将会得到一个编译器错误,因为 xPtr 不是一个 int 型变量,而是*int型,它只能被赋予一个*int型的值。

最后,我们可以使用 & 操作符获取变量的地址。&x 返回的值是 *int 型,因为 x 是 int 类型。这允许我们修改原始变量。main() 函数中的 &x 和 zero() 函数中的 xPtr 指的是相同的内存位置。

new

另外一个获取指针的方法是使用内置函数 new():

func one(xPtr *int) {
  *xPtr = 1
}
func main() {
  xPtr := new(int)
  one(xPtr)
  fmt.Println(*xPtr) // x is 1
}

new() 接受以类型作为参数,分配足够的内存来满足该类型的值,并返回指向该内存的指针。

在一些编程语言中,new() 和 & 之间有很大的区别,需要非常小心的是,最终使用完,需要删除使用 new() 创建的任何内容。Go 却不是这样,它是具有垃圾回收的编程语言,这意味着当变量不再使用时,内存会自动回收。

 

推荐阅读:

指针与引用

彻底学会Go指针

 

如果我的文章对你有所帮助,点赞、转发都是一种支持!

指针(译)_面试

指针(译)_面试_02

 

指针(译)_面试_03