Go 语言中的指针
导入
首先来看下面一段代码:
https://play.studygolang.com/p/RFdfacu1P30
package main import "fmt" func increase(x int) { x += 1 fmt.Println("x inside increase() is ", x) } func main() { x := 1 increase(x) fmt.Println("x outside is ", x) }
输出是:
x inside increase() is 2 x outside is 1
为什么会这样呢?
因为我们向函数increase传递的仅仅是一个值,而不是一个内存中的地址,函数无法获取到该变量内存中的地址,也就无从谈起让函数外的值发生改变。
为了改变这个值,C语言首创了“指针”的用法,Go作为与之一脉相承的语言,自然不会少了这个功能。
正题
我们对上面的程序进行一点小改动,让它变成这个样子:
https://play.studygolang.com/p/Dg9UGkEVMu3
package main import "fmt" func increase(x *int) { *x += 1 fmt.Println("x inside increase() is ", *x) } func main() { x := 1 increase(&x) fmt.Println("x outside is ", x) }
注意我们做出的改动:
-
函数increase的参数部分从
(x int)
变为(x *int)
,强制传入的数据必须是整型指针 -
函数体内
x += 1
变为*x += 1
,代表让传入的指针的值自增1 -
传入输出语句的
x
变为了*x
-
increase(x)
变为了increase(&x)
这时我们再看看输出结果:
x inside increase() is 2 x outside is 2
我们使用*variable = x
来定义一个指针,其中x为它的值。我们可以通过&
操作符来获取一个指向普通变量的内存地址的指针,如上段代码所示。这两种方式是等价的。因此上段代码可以改写为:
package main import "fmt" func increase(x *int) { *x += 1 fmt.Println("x inside increase() is ", *x) } func main() { *x := 1 increase(x) fmt.Println("x outside is ", *x) }
输出仍不变
new函数
go语言内置了一个new
函数,返回一个带初始化值的指针。我们还是来对之前的代码进行更改:
https://play.studygolang.com/p/ta3BZX9hSuJ
package main import "fmt" func increase(x *int) { *x += 1 fmt.Println("x inside increase() is ", *x) } func main() { x := new(int) increase(x) fmt.Println("x outside is ", *x) }
输出:
x inside increase() is 1 x outside is 1
由此可见x指针默认被赋值为0。
习题
请用go语言完成下列习题:
请写出一个函数,它获取一个字符串指针,在字符串结尾添加!
提示:
func add_exclamation_mark(s *string){ }
下集预告
在下一期的让指针飞中,我们会继续讲解go语言,我们将会用更复杂的结构体来演示指针用法。
一个附录
文中多次出现go playground的链接,这里说明一下怎么使用go playground
点击文中的任意链接,在playground的导航栏内找到Run
按钮,运行代码就可以查看效果了。在Go playground中你还可以随意对代码进行更改并运行,自己尝试go的用法。
This post belongs to Column 「让指针飞」 .