文章目录
一、前言
Go系列文章:
- GO开篇:手握Java走进Golang的世界
- 2 Go开发环境搭建、Hello World程序运行
- 3 Go编程规约和API包
- 4 Go的变量、常量、运算符
- 5 Go 基本数据类型
Go专栏传送链接:https://blog.csdn.net/saintmm/category_12326997.html
二、数据类型总览
三、指针
和 C/C++ 中的指针不同,Go中的指针不能进行偏移和运算。它是一种类型指针,可以用于传递数据、对数据进行修改。
简单一点理解:一个指针类型的变量其实就是一个值的内存地址,我们可以通过这个变量的地址(指针)去访问 / 操作数据。
使用指针获取变量内存地址的语法格式:
ptr :=&v
- v 是被取内存地址的变量;
- 变量ptr的类型为
*T
,即T的指针类型,*
代表指针;变量ptr用于接收变量v的内存地址。 - 基本数据类型(又叫值类型),都有对应的指针类型,形式为
*数据类型
。 - 比如:int
的对应的指针为*int
,float32
对应的指针类型为*float32
,依次类推…
1、特殊运算符& *
在Go中 & 和 * 有特殊的用意:
&
:返回变量的存储地址*
:指针取值,取指针变量对应的数值
funcmain(){var age int=18
fmt.Println("age对应的存储空间内存地址为:",&age)// 指针变量 ptr,指向age在存储空间的内存地址var ptr *int=&age
// 指针变量的类型
fmt.Printf("ptr类型为: %T\n", ptr)// ptr指向的内存地址
fmt.Printf("ptr指向的内存地址为:%p\n", ptr)// ptr变量自身的内存地址
fmt.Println("ptr变量自身存储的内存地址为:",&ptr)// 指针取值
value :=*ptr
fmt.Println("ptr这个指针指向的具体数值为:", value)// 取值后的类型
fmt.Printf("value type: %T \n", value)}
控制台输出如下:
- 变量ptr的类型为
*int
; - ptr指针变量的值为指针地址(16进制的整数);
- ptr的指针地址,为变量age的内存地址(0xc0000a6058);
- ptr变量本身也需要一个内存地址(0xc0000ca020)进行存储
- ptr变量的指针取值操作,获取到的值和类型为变量age的值和类型。
2、内存角度来看指针
普通变量:
使用
var age int = 18
声明一个age变量之后,实际在内存中为age变量开辟了一块空间,并且这个空间中存储的数值时18,内存空间会有一个唯一标识(内存地址)。
指针变量:
// 指针变量 ptr,指向age在存储空间的内存地址var ptr *int=&age
// ptr指向的内存地址
fmt.Printf("ptr指向的内存地址为:%p\n", ptr)// ptr变量自身的内存地址
fmt.Println("ptr变量自身存储的内存地址为:",&ptr)
使用
var ptr *int = &age
声明一个ptr指针变量之后,实际在内存中也为ptr变量开辟了一块空间,并且这个空间中存储的数值为age变量的内存地址(
0xc0000a6058
);ptr变临港在内存空间也会有一个唯一标识(内存地址:
0xc0000ca020
)。
3、使用指针修改数据
指针不只可以用来取值,也可以使用来修改值
var num int=10
fmt.Println(num)var ptr *int=&num
*ptr =20
fmt.Println(num)
控制台输出:
上面介绍了
*ptr
为指针取值,这里呢,
*ptr = ?
则直接用于指针赋值,即修改指针地址的数据内容。
4、指针使用的注意事项
1> 指针变量接收的一定是地址值
// 这种方式不允许var prt *int= num
2> 指针变量类型和相应数据的类型不可以不匹配
var num int=10
fmt.Println(num)// 这种方式不允许,ptr指针的类型应该为*intvar ptr *float32=&num
解释:
*float32
意味着指针指向的是float32类型的数据,但是&num对应的是int类型的数据,所以不可以这样操作。
5、对比着看Java的引用类型
Java也是按值传递,但针对引用类型,方法之间传递引用类型的变量实际传递的是变量的内存地址,通过这个变量我们可以直接操作相应类型在内存中的数据;
以下面的代码为例,在method b中修改了变量variable 的某一块数据,在method b 的上层方法method a中也是有感知的,因为它们共享同一块内存地址的数据。
publicclassMain{publicstaticvoidmain(String[] args){a();}publicstaticvoida(){ClassA variable =newClassA(18,"saint");System.out.println("进入method b 方法前:"+ variable.toString());System.out.println("method a 中variable内存地址为:"+ variable.hashCode());b(variable);System.out.println("进入method b 方法后:"+ variable.toString());}publicstaticvoidb(ClassA variable){System.out.println("method b 中variable内存地址为:"+ variable.hashCode());
variable.setAge(28);}@Data@ToStringstaticclassClassA{privateInteger age;privateString name;publicClassA(){}publicClassA(Integer age,String name){this.age = age;this.name = name;}}}
控制台输出:
如果在method b 中对变量variable进行了整体的重新赋值,则变量variable在method b中内存地址发生改变,与method b 上层方法method a中的内存地址不同了。即:它们不在共享同一块内存地址的数据,在method b中修改variable内部的值不会影响method a中的variable变量的数据。
publicstaticvoidb(ClassA variable){
variable =newClassA();System.out.println("method b 中variable内存地址为:"+ variable.hashCode());
variable.setAge(28);}
从方法执行的堆栈信息来看,在method a中variable的内存地址为510,在method b中variable的内存地址为505。
三、总结
指针呢就是内存地址,类比理解为java中的引用类型。额外再记忆两个运算符、一个公式。
两个运算符:
&
:取变量的存储地址*
:指针取值,取指针变量对应的数值
一个公式:
ptr := &v
- v 是被取内存地址的变量;- 变量ptr用于接收变量v的内存地址。- 基本数据类型(又叫值类型),都有对应的指针类型,形式为*数据类型
。 ,比如:int
的对应的指针为*int
。
版权归原作者 秃秃爱健身 所有, 如有侵权,请联系我们删除。