【Go】Go数据类型详解—指针
1. 前言
在我看来,一门编程语言语法的核心就在于数据类型。而各类编程语言的基本数据类型大致相同:int整型、float浮点型、string字符串类型、bool布尔类型,但是在一些进阶数据类型上就有所不同了。本文将会介绍Go语言当中核心的数据类型——指针,这是我们学习后续进阶数据类型的基础
2. 指针
2.1 指针初识
相信大学学过C语言的同学们对这个概念一定不陌生:指针就是数据在内存当中的地址,很多同学都是“谈C色变”,因为在C语言当中指针非常的灵活,学习成本非常高。但是在Go语言当中,指针类型只有两种操作:&取址 和 * 取值,下面就通过一段代码来引入指针
var x = 100
// 取址符:& 取值符:*
fmt.Println("x的地址:", &x)
// 将地址值赋值给的变量称为指针变量
var p *int
p = &x
fmt.Println("p的值:", p)
fmt.Println("p地址对应的值", *p)
这是我的编译器运行结果:上述代码做的事情就是定义了一个变量x,然后使用取址操作符将地址赋值给变量p(由于该变量存储的是地址,因此也被称为指针变量),最后打印了p的值以及使用 *取值操作取出了p指向的地址空间中存储的值,下面就通过图解的方式观察其过程
变量p存储的并不是一个像int之类的简单数据类型,而是一个地址值,因此p也被称为指向整型的指针变量,因此&x以及p的值都是0xc000012070
,使用 *p 操作取值就会通过该地址找到实际存储的值100
2.2 指针练习题
2.2.1 练习题1
// 当使用等号将一个变量的值赋给另一个变量时,如 x = y ,实际上是在内存中将 i 的值进行了拷贝
var x = 10
var y = x
var z = &x
x = 20
fmt.Println(y)
fmt.Println(*z)
*z = 30
fmt.Println(x)
运行结果如下图所示:
画个图就明白了:
💡 解析:执行代码y = x
的过程本质就是发生了值拷贝,分配了一块新的内容空间填充值为10并赋值给y;然后执行代码z = &x
将x的地址0x11赋值给了变量p(如图所示);然后执行代码x = 20
,特别需要注意的是:y此时并不会被修改!!此时打印y的值仍是10;执行代码*z = 30
借助地址修改的0x11空间的20为30,因此打印x的值为30,但是在整个过程中y开辟一块独立空间是不会被修改的
2.2.2 练习题2
var x = 10
var y = &x
var z = *y
x = 20
fmt.Println(x)
fmt.Println(*y)
fmt.Println(z)
运行结果如下图所示:
如果错了的话一定要自己画图!!!
💡 解析:执行代码y = &x
将x的地址0x11赋值给了变量y;然后执行代码z = *y
特别需要注意的是:*y得到的值就是整数10,因此开辟一块新的内存空间存储值10然后赋值给变量z(z并不是指针变量);执行代码x = 20
将0x11地址空间值10改为20,因此打印x的值为20,*y根据地址0x11找到对应存储的值为修改过后的20,但是z的值仍为10不会被更改
2.2.3 练习题3
var a = 100
var b = &a
var c = &b
**c = 200
fmt.Println(a)
运行结果如下图所示:
这个题应该不难做对,关键是要理解每行代码的底层执行流程
💡 解析:本题实际上就是二级指针的运用:执行代码b = &a
将a的地址0x11赋值给了变量b,c = &b
就是将b的空间地址0x22赋值给了c;*c取到的值就是0x22,**c操作取到的值就是a地址空间存储的100了,修改为200之后a取值也即为200了
2.3 new函数
在学习一个新的知识点的时候我们需要理解为什么要引入它?没有这个知识行不行?下面我们来看两段代码的区别:
代码段1:
var x int
x = 10
代码段2:
var p *int
*p = 10
事实上代码段2是会报错的!!!因为*int为指针类型(区别于以往学到的基本数据类型)基本数据类型声明未赋值时会默认零值,但是指针类型默认为nil,不会分配对应的存储空间。之前我们都是通过先定义var x = 10; var p = &x
的方式使用指针,但是现在我想直接声明使用指针应该怎么做呢?这就要使用到new函数了,语法如下:
var p = new(int)
*p = 10
此时new函数底层就会帮助我们初始化一块内存空间并将对应的地址返回
2.4 指针小结
回顾下我们学到的知识:
- 指针在Go语言中可以理解为数据在内存中的地址
- Go语言中的指针没有C语言中偏移、运算等功能,只有&取址操作符和*取值操作符,保证访问高效的同时也保障了内存数据安全
- new函数的作用就是开辟内存空间并将地址返回