本文系第十六篇Golang语言学习教程
指针是一种存储变量内存地址(memory address) 的变量.
如上图, 变量b
的值为156
,b
在内存中的地址是 0x1040a124
, 而变量a
存储了b
的地址, 我们就称a
指向了 b
.
指针的声明
指针变量的类型为 *T
, 该指针指向一个 T
类型的变量. &
用来获取变量的地址.
例:
package main
import "fmt"
func main() {
b := 166 //定义变量 b
var a *int = &b //b 的地址赋给 a, 或说 a 指向 b
fmt.Printf("type of a is %T\n", a) //打印 a 的类型
fmt.Println("address of b is ", a) //打印 a 的值
}
以上程序输出结果为:
type of a is *int
address of b is 0xc420082008
指针的零值
指针的零值是nil
例:
package main
import "fmt"
func main() {
c := 358
var d *int //d 初始化为 nil
if d == nil {
fmt.Println("b is ",d)
d = &c // 给 d 赋值 c 的地址
fmt.Println("after init b is ", d)
}
}
以上程序中,可以看到 b 的初始值为 nil.
输出为:
b is <nil>
after init b is 0xc42008e030
指针的解引用
指针的接引用可以获取指针指向变量的值, 将 a
解引用的语法是 *a
.
例:
package main
import "fmt"
func main() {
b := 166 //定义变量 b
var a *int = &b //b 的地址赋给 a, 或说 a 指向 b
fmt.Printf("type of a is %T\n", a) //打印 a 的类型
fmt.Println("address of b is ", a) //打印 a 的值
fmt.Println("b is ", *a) // 解引用 a
*a++ //给 *a +1 ,等于给 b + 1
fmt.Println("new b is ", b)
}
以上程序中, 首先接引用*a
, 返回 b
的值. 然后给 *a
+1 ,相当于改变 b
的值.
输出为:
type of a is *int
address of b is 0xc420014070
b is 166
new b is 167
向函数传递指针参数
package main
import "fmt"
func change(val *int) {
*val = 66
}
func main() {
e := 77
fmt.Println("val of e befor is ", e)
f := &e // f 等于 e 的地址
change(f) //函数解引用修改传入参数 f
fmt.Println("val of f after is ", e)
}
以上程序中, 首先定义函数change
, 传入类型为 *int
, 并将传入参数解引用修改值为66. f 存储了 e 的地址, 当调用change
参数时, 解引用 f 并改变值为 66.
输出为:
val of e befor is 77
val of f after is 66
不要向函数传递数组的指针, 而应该使用切片
package main
import "fmt"
func modify(arr *[3]int) {
(*arr)[0] = 20 //将 arr 解引用, 并将第一个元素赋 20
}
func main() {
a := [3]int{40,50,60} //创建一个数组 a
modify(&a)
fmt.Println(a)
}
在以上程序中, 定义函数modify
, 传入参数arr
是一个*[3]int
类型的值.
调用函数后, 将 arr 解引用, 并给第一个元素赋值 20.
输出为:[20 50 60]
a[x] 是 (*a)[x] 的简写, 所以以上程序可以写为:
package main
import "fmt"
func modify(arr *[3]int) {
arr[0] = 20 //将 arr 解引用, 并将第一个元素赋 20
}
func main() {
a := [3]int{40,50,60} //创建一个数组 a
modify(&a)
fmt.Println(a)
}
但在 GO 语言中,我们最好用切片来实现以上功能.
package main
import (
"fmt"
)
func modify(arr []int) { //传入参数为切片类型
arr[0] = 20
}
func main() {
a := [3]int{40,50,60} //创建一个数组 a
modify(a[:]) // 传入一个切片
fmt.Println(a)
}
以上程序中,创建了函数 modify
, 传入参数为切片类型 .
创建一个切片传入函数, 函数将切片的第一个元素改为20.
输出为:[20 50 60]
所以别再传递数组指针了,而是使用切片吧。上面的代码更加简洁,也更符合 Go 语言的习惯。
最后, GO 并不支持指针运算.
以上为学习Golang 指针篇