当我们调用一个带有参数的函数是,参数是原值的拷贝:
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 却不是这样,它是具有垃圾回收的编程语言,这意味着当变量不再使用时,内存会自动回收。
推荐阅读:
如果我的文章对你有所帮助,点赞、转发都是一种支持!