指针
学过 C 语言中的指针, 就可以理解为 Go 语言的指针, Go 语言中的指针是比较克制的
- 指针是一种存放内存地址的数据类型
- 指针总是会指向一块特定的内存空间
- 指针在go语言中不能直接参与运算(需要使用 unsafe 包中的方法)
指针变量
go
package main
import "fmt"
func main() {
num := 1 // 普通变量, 保存的是具体的数据
fmt.Println(num) // 10
numPtr := &num // 指针变量, 保存的是内存地址
fmt.Println(numPtr) // 0xc0000120c0
fmt.Println(*numPtr) // 解引用:通过内存地址获取这个空间中保存的数据内容
}取地址符 与 解引用符
- 取地址符:
& - 解引用符:
*
悬垂指针
也叫做: 野指针 空指针
它表示, 声明了指针变量, 但是没有指向任何内存地址, 这种指针变量是没有意义的
go
package main
import "fmt"
func main() {
var x *int
// 这个 nil 相当于 C 语言中的 NULL
fmt.Println(x) // <nil>
fmt.Println(*x) // 0x00
}指针初始化
- 推荐使用内置方法:
new - 如果变量已经存在可以使用取地址符:
&varName
go
package main
import "fmt"
func main() {
// 注意:
// 1.new 方法的返回值是一个指针类型的值(内存地址)
// 2.由于需要返回一个指针,所以传入的是类型(需要根据类型计算需要多少内存空间)而不是具体的值
intPtr := new(int) // 初始化指针变量
*intPtr = 10 // 解引用赋值
fmt.Println(*intPtr)
num := 20
numPtr := &num
fmt.Println(*numPtr)
}nil 详解
nil 代表的是 Go 语言中的空值(或者叫零值)
nil 是标识符, 不是一种数据类型(
用于表示指针变量没有指向具体内存地址的状态)Go 语言中的不同数据类型的零值(可以简单的理解为
默认值)- bool: false
- int/uint等数字类型: 0
- string: ""
- array(如: [3]int): []
- struct 没有零值, 但内部的字段有零值
- pointer/slice/map/channel/func/interface: nil
由
3可以知:只有数据存在堆区的数据类型的默认值是nil, 这样证明了2
go
package main
import "fmt"
func main() {
// 这样是不行的, 数组的数据存在栈区
// var nums [3]int = nil
// fmt.Println(nums)
// 这样是可以的, 切片的数据存在堆区
var nums []int = nil
fmt.Println(nums)
}堆内存 & 栈内存
Go 是站在 C 这个巨人的肩膀上创造出来的, 但是其底层 的处理还是离不开C中的一些概念(比如: 堆内存 栈内存)
- 栈内存: 随函数调用创建, 函数返回时自动销毁
- 堆内存: 手动分配, 需要显式释放(或由垃圾回收器管理)
这一点在C 语言中比较明显, 在 Go 语言中反而不太明显, Go 为了 更简单(不需要手动管理内存), 就需要垃圾回收器, 但是偏偏它又支持直接操作内存地址, 但这也就导致了, 内存操 作不透明, 都是黑魔法, 内存相关操作, 理解起来比 C 还费劲