内容简介:我们知道,变量的本质对一块内存空间的命名,可以通过引用变量名来使用这块内存空间存储的值,而指针的含义则指向存储这些变量值的内存地址。和 PHP、Java 不同,Go 语言支持指针,如果一个变量是指针类型的,那么就可以用这个变量来存储指针类型的值:如上,你可能记得 PHP 中也有类似通过
指针概述
我们知道,变量的本质对一块内存空间的命名,可以通过引用变量名来使用这块内存空间存储的值,而指针的含义则指向存储这些变量值的内存地址。和 PHP 、 Java 不同,Go 语言支持指针,如果一个变量是指针类型的,那么就可以用这个变量来存储指针类型的值:
a := 100 var ptr *int ptr = &a fmt.Println(ptr) fmt.Println(*ptr)
如上, ptr
就是一个指针类型,表示指向存储 int
类型值的指针。我们可以通过 *ptr
获取指针指向内存地址存储的变量值(我们通常将这种引用称作「间接引用」), ptr
本身是一个内存地址值(通过 &a
可以获取变量 a
所在的内存地址),所以上述代码打印结果是:
0xc0000a2000 100
你可能记得 PHP 中也有类似通过 &
进行引用传值的用法(数组传值需要,对象传值不需要,因为对象本身是引用类型),其实这种用法的本质也是指针,只不过 PHP 的语言级别屏蔽了指针的概念而已。
Go 语言之所以引入指针类型,主要基于两点考虑,一个是为 程序员 提供操作变量对应内存数据结构的能力;另一个是为了提高程序的性能(指针可以直接指向某个变量值的内存地址,可以极大节省内存空间,操作效率也更高),这在系统编程、操作系统或者网络应用中是不容忽视的因素。
指针在 Go 语言中有两个使用场景:
- 类型指针
- 数组切片
作为类型指针时,允许对这个指针类型的数据进行修改指向其它内存地址,传递数据时如果使用指针则无须拷贝数据从而节省内存空间,此外和 C 语言中的指针不同,Go 语言中的类型指针不能进行偏移和运算,因此更为安全。
数组切片我们前面已经介绍过,由指向起始元素的原始指针、元素数量和容量组成,所以切片与数组不同,是引用类型,而非值类型。
指针的基本使用
下面我们以一个简单的示例代码来演示 Go 语言中指针的基本使用。
指针类型的声明和初始化
指针变量在传值时之所以可以节省内存空间,是因为指针指向的内存地址的大小是固定的,在 32 位机器上占 4 个字节,在 64 位机器上占 8 个字节,这与指针指向内存地址存储的值类型无关。
关于指针类型的声明我们在开头已经演示过,这里我们再回头看下这段代码:
var ptr *int fmt.Println(ptr) a := 100 ptr = &a fmt.Println(ptr) fmt.Println(*ptr)
当指针被声明后,没有指向任何变量内存地址时,它的零值是 nil,然后我们可以通过在给定变量前加上取地址符 &
获取变量对应的内存地址将其赋值给声明的指针类型,这样,就是对指针的初始化了,然后我们可以通过在指针类型前加上间接引用符 *
获取指针指向内存空间存储的变量值。当然,我们也可以通过 :=
对指针进行初始化:
a := 100 ptr := &a fmt.Printf("%p\n", ptr) fmt.Printf("%d\n", *ptr)
底层会自动判断指针的类型,在格式化输出时,可以通过 %p
来标识指针类型。
通过指针传值
我们再来看一个通过指针传值的示例,通过指针传值就类似于 PHP 中通过引用传值,这样做的好处是节省内存空间,此外还可以在调用函数中实现对变量值的修改,因为直接修改的是指针指向内存地址上存储的变量值,而不是值拷贝。
为了体现出区别,我们先看不使用指针的值拷贝示例:
func swap(a, b int) { a, b = b, a fmt.Println(a, b) } func main() { a := 1 b := 2 swap(a, b) fmt.Println(a, b) }
上述代码的打印结果是:
下面我们通过指针传值来重构上述代码:
func swap(a, b *int) { *a, *b = *b, *a fmt.Println(*a, *b) } func main() { a := 1 b := 2 swap(&a, &b) fmt.Println(a, b) }
上述代码的打印结果是
因为这次,我们是通过指针传值的( &a
、 &b
都是指针,只不过我们没有显示声明而已),直接会对内存地址存储变量值进行交换操作,而主函数中的 a
、 b
变量仅仅是对应内存存储空间的别名而已,所以调用完 swap
函数后,它们所对应的内存空间存储值已经交换过来了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- python(函数指针和类函数指针)
- 将数组和矩阵传递给函数,作为C中指针的指针和指针
- C/C++ 函数指针
- flag 中的 Go 函数指针
- CGO 中传递回调函数和指针
- GOLAMG-5 type 不同于C/C++ typedef,切片底层是指针域的函数指针
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。