前言
对于指针,C语言可是靠着这个东西混的游刃有余,go创作初继承了大量C的属性,所以指针就是必不可少的,而go的指针和C也有很大不同。咱们也不用深究不同点,只要知道指针是存储一个变量内存地址的,它本身也是一个变量。
1. 获取变量的地址
在go语言中取地址符为&,往往放到一个变量的前面,用来返回相应的内存地址
var a int = 1
fmt.Printf("变量的地址: %x\n", &a)
变量的地址: c0000aa058
2. 声明指针
一般的格式为*T,T表示的是变量类型
var a int = 10 /* 声明一个实际变量 */
var b *int /* 声明一个指针变量 */
b = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a)
/* 指针变量的存储地址 */
fmt.Printf("ip 变量的存储地址: %x\n", b)
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *b)
a 变量的地址是: c000018098
ip 变量的存储地址: c000018098
*ip 变量的值: 10
如果一个指针被定义了但是没有赋予任何变量,那么它就是一个空指针,值为nil
3.指针的一系列操作
获取指针就是访问指针指向变量的值,语法就是*a
3.1操作指针改变变量的数值
a := 100
b := &a
fmt.Println("a的地址是", b)
fmt.Println("a的值是", *b)
*b++
fmt.Println("a的新值是", a)
a的地址是 0xc000018098
a的值是 100
a的新值是 101
3.2用指针在函数里传参
func foo(a *int) {
*a = 12
}
func main() {
b := 15
fmt.Println("在改变之前b的值为", b)
c := &b
foo(c)
fmt.Println("在改变之后b的值为", b)
}
在改变之前b的值为 15
在改变之后b的值为 12
如果函数的参数是数组,就不要用指针指向它,也就是说,函数的参数不能是用指针指向的数组,要使用切片
func foo(arr *[3]int) {
arr[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
foo(&a)
fmt.Println(a)
}
[90 90 91]
虽然上面的结果正确,但这并不是实现这一目标好用的方法,相对而言还显得复杂,我们不妨用切片来试试
func foo(arr []int) {
arr[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
foo(a[:])
fmt.Println(a)
}
[90 90 91]
在开发的过程中我们有可能需要保存原数组,指针就是不错的选择
const MAX int = 3
func main() {
a := []int{110, 111, 112}
var i int
var arr [MAX]*int
for i = 0; i < MAX; i++ {
arr[i] = &a[i] /* 整数地址赋值给指针数组 */
}
for i = 0; i < MAX; i++ {
fmt.Printf("a[%d] = %d\n", i, *arr[i])
}
}
a[0] = 110
a[1] = 111
a[2] = 112
4.指向指针的指针
如果一个指针存的是另一个指针的地址,则这个指针变量就是指向指针变量的指针
var a int
var arr *int
var aarr **int
a = 100
/* 指针 arr 地址 */
arr = &a
/* 指向指针 arr 地址 */
aarr = &arr
/* 获取 aarr 的值 */
fmt.Printf("变量 a = %d\n", a)
fmt.Printf("指针变量 *arr = %d\n", *arr)
fmt.Printf("指向指针的指针变量 **aarr = %d\n", **aarr)
变量 a = 100
指针变量 *arr = 100
指向指针的指针变量 **aarr = 100
函数的参数是指针
func swap(x *int, y *int) {
var tem int
tem = *x /* 保存 x 地址的值 */
*x = *y /* 将 y 赋值给 x */
*y = tem /* 将 temp 赋值给 y */
}
func main() {
/* 定义局部变量 */
var a int = 10
var b int = 20
fmt.Printf("变化前 a 的值为 : %d\n", a)
fmt.Printf("变化前 b 的值为 : %d\n", b)
/* 调用函数用于交换值
* &a 指向 a 变量的地址
* &b 指向 b 变量的地址
*/
swap(&a, &b)
fmt.Printf("变化后 a 的值为 : %d\n", a)
fmt.Printf("变化后 b 的值为 : %d\n", b)
}
变化前 a 的值为 : 10
变化前 b 的值为 : 20
变化后 a 的值为 : 20
变化后 b 的值为 : 10