指针

十三、指针

相比于c或c++,go语言的指针是很容易学习的,它可以更简单地执行一些任务。

1 取地址操作符&

变量是一种使用方便的占位符,用于引用计算机内存地址,使用&符号获取变量的内存地址,如下:

func main() {
	var str = "hello world"
	fmt.Println(&str)
    // 返回结果为0xc00004c230
}

2 指针的定义

指针是一个变量,这个变量存储了另一个变量的内存地址。

在使用指针前,你需要声明指针。指针声明格式如下

var var_name *var-type
// var_name 为指针变量名
// var-type 为指针类型

举例:

var ptr1 *string // 指向字符串
var ptr2 *int  // 指向整型

当一个指针被定义后没有分配到任何变量时,它的初始值为nil,也被称为空指针

func main() {
	var ptr *int
	fmt.Println(ptr) // 未分配的指针初值为<nil>
	fmt.Println(&ptr) // 指针作为一个变量,也可以取到它的内存地址
    fmt.Println(*ptr) // 未分配的指针,获取指针指向的内容时会报错panic: runtime error: invalid memory address or nil pointer dereference
}

3 使用指针

定义指针后,需要给指针变量赋值,使用*操作符可以获取指针指向的内容(也称解引用)。

func main() {
	var ptr *int // 声明指针变量,它指向一个整型变量,初始化一个空指针
	b := 3   // 创建变量b为整型变量
	ptr = &b  // 将变量b的内存地址赋值给指针,也称'指针ptr指向了b'
	fmt.Println(ptr)
	fmt.Println(b)
  	fmt.Println(*ptr) // 指针解引用,获取指针所指向的变量的值
}

4 指针的函数传递

指针也是一个变量,可以向函数传递。

func add(ptr *int) {
	*ptr++
}
func main() {
	a := 10
	var ptr *int = &a
	add(ptr)
	print(a)
}

5 指针运算

与c和c++不同,go中的指针不支持对指针运算,比如指针的递增和递减。

a := 10
var ptr *int = &a
ptr++ // 不支持指针运算,返回错误invalid operation: ptr++ (non-numeric type *int)

6 多级指针

已知指针本身也是变量,指针存放的是变量的内存地址。所以,可以让一个指针存放另一个指针变量的地址,此时称这个指针变量为指向指针的指针(二级指针)。

a := 10
var ptr *int = &a
var pptr **int
pptr = &ptr
fmt.Println(a) // 10
fmt.Println(ptr) // 0xc0000160b8
fmt.Println(pptr) // 0xc000006028
fmt.Println(*pptr) // 0xc0000160b8
fmt.Println(**pptr) // 10

如上面的例子,二级指针解引用时,需要使用两个*

同理,你可以“无限套娃”下去,定义多级指针。

下面是一个三级指针、四级指针的例子:

a := 10
var ptr *int = &a
var pptr **int
var ppptr ***int
var pppptr ****int
pptr = &ptr
ppptr = &pptr
pppptr = &ppptr
fmt.Println(a)
fmt.Println(ptr)
fmt.Println(pptr)
fmt.Println(ppptr)
fmt.Println(pppptr)
上一篇:C++解决share_ptr造成的循环引用


下一篇:6.go基础入门-判断(if)、循环(for)、指针(ptr)、数组(array)