携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情
什么是指针
程序运行时数据是存放在内存中的。计算机中将内存抽象为一系列具有连续编号的存储空间,每个存储在内存中的数据都有一个编号,这个编号就是内存地址。通过内存地址就能找到存储在内存中的数据。在Golang 中内存地址赋值给指针。
所以,指针,是一种数据类型,用来存储内存地址的。
指针的使用
var strP *string
name := "tom"
strP = &name
fmt.Println("name变量的值为:",name)
fmt.Println("name变量的内存地址为:",strP)
符号 & 用于取地址的,&name
获取变量 name 的内存地址并赋值给指针变量 strP ,该指针变量的类型是 *string。在 Go 语言中使用类型名称前加 * 的方式,即可表示一个对应的指针类型。
运行上面的示例可以看到如下结果
name变量的值为: tom
name变量的内存地址为: 0x140001966b0
name 是普通变量,strP 是指针类型变量。&name 的值是内存地址,当然 strP 也是需要一块内存来存储的,所以当 &strP 获取到是指针类型变量的内存地址,strP存储着 name 的内存地址。
指针声明
- 使用关键字 var 定义
var strP *string
通过 var 声明的指针变量是不能直接赋值和取值的,因为这时候它仅仅是个变量,还没有对应的内存地址,它的值是 nil。
- 使用 new 函数声明
intP := new(int)
指针操作
- 获取指针指向的值
name := "tom"
strP = &name
fmt.Println("strP指针指向的值为:",*strP)
// 结果
strP指针指向的值为: tom
通过在指针变量前加 * 号就可以获取到指针指向的值
- 修改指针指向的值
name := "tom"
strP = &name
*strP = "jerry" //修改指针指向的值
fmt.Println("strP指针指向的值为:",*strP)
fmt.Println("name变量的值为:",name)
// 结果
strP指针指向的值为: jerry
name变量的值为: jerry
通过 *nameP 赋值等于修改了指针 nameP 指向的值。因 strP 指针存的是 name 的内存地址,所以修改指针指向的值就相当于也修改了变量 name 的值。
因 var 定义的指针变量是不能赋值的,它的值是 nil ,未指向内存地址。所以可以使用 new 函数给它分配一个内存即可。
var strP *string = new(string)
指针参数
使用指针作为参数时,在函数内修改形参的值也会改变实参的值。
func changeNum(num *int) {
*num = 12
}
// 使用
func main() {
num := 18
fmt.Println("num的值为:", num)
changeNum(&num)
fmt.Println("num的值为:", num)
}
// 结果
num的值为: 18
num的值为: 12
指针接收者
指针作为函数的接受者,当遇到以下情况可使用指针
- 接收者是比较大的类型,因内存传递效率高,所以可使用指针
- 需要修改接受者时,可使用指针
- 当接收者是 map ,slice ,channel 类型时,不用使用指针,因为它们就是引用类型
所以,如果使用指针的话,有很大的好处:
- 变量赋值、传值可以节省内存,只需读取内存地址即可
- 通过获取指针存储的内存地址即可直接修改内存地址所指向的值。