Go 指针的使用

174 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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 类型时,不用使用指针,因为它们就是引用类型

所以,如果使用指针的话,有很大的好处:

  • 变量赋值、传值可以节省内存,只需读取内存地址即可
  • 通过获取指针存储的内存地址即可直接修改内存地址所指向的值。