GO语言也有指针,本质上和C/C++没有差别,但是在用法上有很多差别,GO语言中的指针是弱化版的C/C++指针。
先来看一段简单的代码
func main() {
a := 1
b := &a
fmt.Println(reflect.TypeOf(b),b,*b)
}
执行结果如下
*int 0xc04204e080 1
由此可见:
- 这个b的类型就是int类型的指针,用*int表示
- b指向了a,b的值就是a的地址,也就是说a的地址就是0xc04204e080
- *b就是解引用指针,得到的是a的值,也就是1
基本的用法看起来和C++好像没有太大的变化,但是还是有几点是需要注意的。
指针的零值
C/C++中指针可以为NULL,那么在GO语言中,空指针就是nil了,这也是我们说的指针的零值(不赋值时候的值)。
GO语言中的指针不能拿来运算
GO语言中的指针是简单的,弱化版的C/C++指针,就是因为GO语言规定指针不可以进行运算,而C/C++中的指针可以进行++/--操作,也可以进行+1,+2这样的运算操作,GO语言简单就是简单在它规定了这样的操作是不合法的,编译器会自动报错。
值传递配合指针实现引用传递
在函数传参的时候,GO语言只有值传递一种方式,没有引用传递。
来看下面的代码
func print(a int){
fmt.Println(a)
}
func main() {
a := 1
print(a)
}
这就是典型的值传递,才调用print函数的时候,会拷贝一份变量a,作为形式参数传给print函数,调用完print函数之后,这个临时的拷贝的变量就被销毁了。这中间有一次拷贝操作,如果这个变量不是int,而是一个自定义类型,且这个类型的大小非常大。那我们如果拷贝了这个变量,肯定就会消耗一定的空间。
这个时候我们就可以使用指针来搞定,同时这也保证了,这次值传递传递的是变量的地址,而不是整个变量,起到了引用传递的效果。
func print(pa *int){
*pa = 2 //将pa指向的地址的值改为了2
fmt.Println(*pa)
}
func main() {
a := 1
fmt.Println(a) //执行print函数之前a是1
print(&a)
fmt.Println(a) //执行print函数之后a是2
}
来看下输出结果
1
2
2
a的值在调用完print函数以后发生了变化,是因为print函数体内通过指针改变了原来的值,这个C语言的实现的引用传递方式类似。