前言
最近在学习 go 语言,了解到指针,初看有些迷糊,自己仔细梳理了下,算是明白了,在此记录下。
说明
go 语言的指针借鉴了 c,所以很多地方都有共同的地方
一、内存结构
程序内所有的赋值取值,都是在内存中进行写入、读取操作。
而写入数据时,内存要保存数据的值、数据的类型、数据的名称以及数据的地址;
内存的基本单位
多个单位组成的内存 图像表示
二、指针运算符
首先看看指针运算所用到的符号
&
【取地址】,取地址运算符;获取变量在内存中的地址
*
【取值】,间接运算符/取消引用运算符;获取某个内存地址保存的值
功能介绍
1 2 3 4 5
| var number int = 10
fmt.Println("number内存地址为:", &number) fmt.Println("number在内存的值为:", *(&number))
|
上面案例就是一个简单明了的运算符使用
&
:可以获取变量在内存中的地址
*
:可以根据内存地址,取到该地址保存的值。因此也被称为指针。
使用
程序中一般用于将内存地址赋值给其他变量
1 2 3 4 5
| var number int= 5 var p *int= &number
fmt.Println("p在内存的值为:", p)
|
go 语言中*int
表示获取int
类型变量在内存中的地址,也还有*string
、*float32
等等。指针类型变量只能保存同一类型变量的地址
当然,在实际使用中,*
往往与 &
配合使用
1 2 3 4 5 6 7 8 9
| var number int= 5 var p *int= &number
*p = 100 fmt.Println("p在内存的值为:", p) fmt.Println("*p在内存的值为:", *p) fmt.Println("number在内存的值为:", number) fmt.Println("number在内存的值为:", *(&number))
|
解析:
var p *int= &number
,保存的是number
在内存中的地址
*p = 100
则相当于 *(&number)=100
;等同于 number=100
因此*
也被称为指针运算符;***
不仅可以根据内存地址找到对应的值,还可以对该地址保存的值进行修改**
实际使用
上面代码仅作原理展示。
实际使用中往往用于不同方法间传递一个不受方法作用域限制的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main import "fmt"
func changeValue(p int) { p = 10 }
func swap(p *int) { *p = 10 }
func main() { var a int = 1
changeValue(a) fmt.Println("a = ", a)
swap(&a) fmt.Println("a = ", a) }
|
扩展
*int
、*string
、*float32
…等等这些被称为一级指针类型变量
**int
、**string
、**float32
…等等被称为二级指针
指针类型可以有多级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package main
import "fmt"
func main() { var number int = 5
var p *int = &number var pp **int = &p var ppp ***int = &pp
*p = 100
fmt.Println("number在内存的值为:", number) fmt.Println("number在内存的地址为:", &number)
fmt.Println("p在内存的值为:", p) fmt.Println("*p在内存的值为:", *p) fmt.Println("p在内存的地址为:", &p)
fmt.Println("pp在内存的值为:", pp) fmt.Println("pp在内存的地址为:", &pp)
fmt.Println("ppp在内存的值为:", ppp) fmt.Println("*ppp在内存的值为:", *ppp) fmt.Println("**ppp在内存的值为:", **ppp) fmt.Println("***ppp在内存的值为:", ***ppp)
***ppp = 200 fmt.Println("number在内存的值为:", number) }
|