指针
任何指针的零值都是 nil
1. 基础内容
1.1. 指针的基本用法
指针不能运算,Go 语言只有值传递一种方式,引用类型,也会拷贝引用的地址
|
|
1.2. 指针相等的条件
- 都是
nil
- 指向同一个变量
在 Go 语言中,返回函数中局部变量的地址也是安全的
1.3.new 预定义函数
new(T)
将创建一个 T 类型的匿名变量,初始化T 类型零值,返回变量地址,类型是 *T
new
是预定义函数,并非关键字,可以更改类型,声明为变量等操作,但不建议这样干!
|
|
struct{}
和[0]int
是大小为 0 的类型,(请谨慎使用大小为0的类型,因为这样可能会导致Go语言的自动垃圾回收器有不同的行为,具体请查看runtime.SetFinalizer
函数相关文档)。
1.4.变量的生命周期
包级别的变量,生命周期和程序的运行周期一致
函数的参数和返回值都是局部变量,在函数被调用的时候创建,函数的生命周期(栈帧)结束销毁
Golang 语言的自动垃圾回收,这里避开实现细节,说一下思路 :
从每个包级的变量和每个当前运行函数的每一个局部变量开始,通过指针或引用的访问路径遍历,是否可以找到该变量。如果不存在这样的访问路径,那么说明该变量是不可达的,也就是说它是否存在并不会影响程序后续的计算结果。
因为一个变量的有效周期只取决于是否可达,因此一个循环迭代内部的局部变量的生命周期可能超出其局部作用域。同时,局部变量可能在函数返回之后依然存在。
编译器会自动选择在栈上还是在堆上分配局部变量的存储空间,选择并不是由用var还是new声明变量的方式决定
|
|
其实在任何时候,你并不需为了编写正确的代码而要考虑变量的逃逸行为,要记住的是,逃逸的变量需要额外分配内存,同时对性能的优化可能会产生细微的影响。
如果将指向短生命周期对象的指针保存到具有长生命周期的对象中,特别是保存到全局变量时,会阻止对短生命周期对象的垃圾回收(从而可能影响程序的性能)。
2. 使用案例
2.1. 使用指针实现 Echo 命令
|
|
2.2. 使用指针来交换变量
|
|
|
|
- 要改变内容必须使用指针接收者
- 结构过大也考虑使用指针接收者( 避免大量拷贝浪费性能 )
- 一致性: 如有指针接收者, 都使用指针接收者 ( 纯属为方便 )