Go基础之指针 | 青训营

261 阅读4分钟

指针

一个变量对应一个保存了变量对应类型值的内存空间。普通变量在声明语句创建时被绑定到一个变量名,比如叫x的变量,但是还有很多变量始终以表达式方式引入,例如x[i]或x.f变量。所有这些表达式一般都是读取一个变量的值,除非它们是出现在赋值语句的左边,这种时候是给对应变量赋予一个新的值。
一个指针的值是另一个变量的地址。一个指针对应变量在内存中的存储位置。并不是每一个值都会有一个内存地址,但是对于每一个变量必然有对应的内存地址。通过指针,我们可以直接读或更新对应变量的值,而不需要知道该变量的名字(如果变量有名字的话)。

声明指针

指针是一种地址值,这个地址值代表着计算机内存空间中的某个位置。指针变量就是存放地址值的变量,指针变量的声明格式如下:

var 指针变量名 *数据类型
例:var p *int

一般情况下,我们将指针变量的类型声明为*int,变量名为“p”开头(指代“point”)的单词,如“p”或“ptr”。

package main
import "fmt"

func main(){
    var p *int
    fmt.Println(p)
}

执行结果:

<nil>

由于指针变量未指向任何地址,所以打印值为nil。

取指针变量地址

取址运算符"&"用于获取对象地址。

package main
import "fmt"

func main(){
    num := 1
    var p *int = &num  //将取得num的地址值赋给指针变量
    fmt.Println("num变量的地址为:",p)
    fmt.Println("指针变量p的地址为:",&p)
}

执行结果:

num变量的地址为: 0xc042066080
指针变量p的地址为: 0xc042086018

由于指针变量本身也是变量,因此指针变量在计算机内存中也有自己的地址。需注意的是,读者运行上述程序时得到的实际结果可能与以上结果不符,甚至多次运行该程序得到的结果可能都不一致,这是由于变量在内存中的位置都是随机分配的。

获取指针所指向的内容

指针变量存储的值为地址值,通过在指针变量前面加上“*”符号可以获取指针所指向地址值的内容。

package main
import "fmt"

func main(){
    num := 1
    var p *int = &num  //将取得num的地址值赋给指针变量
    fmt.Println("num变量的地址为:",p)
    fmt.Println("指针变量p的地址为:",&p)
    fmt.Println("指针变量p所指向的内容:",*p)
}

执行结果:

num变量的地址为: 0xc042066080
指针变量p的地址为: 0xc042086018
指针变量p所指向的内容: 1

注意:p指针声明后其值为nil,这时如果获取指针p指向的地址内容,则会出错

package main
import "fmt"

func main(){
    var p *int
    fmt.Println("num变量的地址为:",p)
    fmt.Println("指针变量p所指向的内容:",*p)
}

执行结果:

指针变量p指向的地址为: <nil>
panic: runtime error: invalid memory address or nil pointer dereference

使用指针修改值

在指针变量有实际指向的地址值后,可以通过如下格式直接修改指针所指向内存地址的内容:

*变量名 = 修改值
package main
import "fmt"

func mian(){
    num := 1
    var p *int = &num  //将取得num的地址值赋给指针变量
    fmt.Println("指针变量p所指向的内容:",*p)
    *p = 10
    fmt.Println("指针变量p所指向的内容:",*p)
}

执行结果:

指针变量p所指向的内容: 1
指针变量p所指向的内容: 10

在使用指针修改值时也需注意,可使用new()函数来给指针分配地址并初始化地址对应的值。

package main
import "fmt"

func mian(){
    var p *int 
    p = new(int)
    fmt.Println("指针变量p所指向的内容:",*p)
    *p = 10
    fmt.Println("指针变量p所指向的内容:",*p)
}

执行结果:

指针变量p所指向的内容: 0
指针变量p所指向的内容: 10