跳到主要内容

指针类型

1.1、指针的基本使用

计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如 int 占用 4 个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就像门牌号、身份证号一样,每个字节的编号是唯一的,根据编号可以准确地找到某个字节。

我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF。

数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量

Go语言中使用对于指针存在两种操作: 取址取值

| 符号 | 名称 | 作用 |

| :-------- | :----- | :--------------------- |

| &变量 | 取址符 | 返回变量所在的地址 |

| *指针变量 | 取值符 | 返回指针指地址存储的值 |


var x = 100

// 取址符:& 取值符:*
fmt.Println("x的地址:", &x)

// 将地址值赋值给的变量称为指针变量
var p *int

p = &x

fmt.Println("p的值:", p)
fmt.Println("p地址对应的值", *p)

image-20210607171319554

关于地址的格式化打印

var x = 10
fmt.Printf("%p\n", &x)

x = 100
fmt.Printf("%p\n", &x)
fmt.Println(*&x)

关于指针的应用:

// 当使用等号将一个变量的值赋给另一个变量时,如 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)

练习1

var x = 10
var y = &x
var z = *y

x = 20

fmt.Println(x)
fmt.Println(*y)
fmt.Println(z)

练习2

var a = 100
var b = &a
var c = &b

**c = 200

fmt.Println(a)

提示
  1. Go语言的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移和运算,从而避免了非法修改关键性数据的问题。

1.2、new函数

new 和 make 是 Go 语言中用于内存分配的原语。简单来说,new 只分配内存,make 用于初始化 slice、map 和 channel。

之前我们学习的基本数据类型声明之后是有一个默认零值的,但是指针类型呢?

var p *int

// fmt.Println(p) // <nil>

// fmt.Println(*p) // 报错,并没有开辟空间地址

*p = 10. // 报错

我们可以看到初始化⼀个指针变量,其值为nil,nil的值是不能直接赋值的。通过内建的new函数返回⼀个指向新分配的类型为int的指针,指针值为0xc00004c088,这个指针指向的内容的值为零(zero value)。

	var p *int = new(int)

fmt.Println(p) // 0x14000122008
fmt.Println(*p) // 0

*p = 10
fmt.Println(*p) // 10

截屏2022-07-30 23.15.24

提示

make返回的还是引⽤类型本⾝;⽽new返回的是指向类型的指针。后面再详细介绍