1、变量
1.1变量声明
长声明:var name type = expression
短声明:name := expression (短声明不能用于全局变量)
1.2变量的生命周期
生命周期:指程序执行过程中变量存在的时间段
1.2.1变量的分配空间(堆或栈)
关于编译器对于变量分配的空间是堆还是栈,不是基于var或new(下面会介绍) 来判断的。下面有两个函数f()和g():
var global *int func f() { var x int x = 1 global = &x } func g() { y := new(int) *y = 1 }
这里局部变量x将会分配到堆,而y将会分配到栈。
因为x将会从f()中逃逸出来,因为f()返回后,依旧可以从全局变量global继续访问,
而很明显y并没有从g()中逃逸。
1.2.2垃圾回收机制
当变量的生命周期结束(不可访问),这时变量占有的存储空间就会被回收。
如何判断变量是否应该被回收?
基本思路是:每一个包级别的变量和每一个当前执行函数的局部变量,可以作为追溯该变量的路径的源头,通过指针和其他方式的引用可以找到变量。如果变量的路径不存在,那么变量变得不可访问,因此它不会影响如何其他的计算过程。
因为变量的生命周期是通过它是否可达来确定的,所以局部变量可在包含他的循环的一次迭代之外继续存活。
2.指针和new
2.1指针
指针的值是一个变量的地址,不是所以的值都有地址,但所有的变量都有。
GO的指针和C指针的定义和使用(使用*)基本相同。
GO指针的零值为:nil
2.2new函数
还有一种比较特殊的变量创建方法:new
表达式:new(T) 将会创建一个未命名的T类型变量
初始化为T类型的零值,并返回其地址(地址类型为*T)
使用new创建的变量和取其地址的普通局部变量没有什么不同,仅语法上更便利。
p := new(int) q := new(int) fmt.Println(p == q) //false
例如上述代码:p和q为两个*int,且各自分配了不同的地址。
注意有个例外:当两个变量的类型不携带任何信息且都为零值时,当前的实现里他们具有相同的地址,例:struct{} 或者 [0]int
(补充:这个例外是我买的 GO语言程序设计 书籍上所说,但是我在检验的过程中发现无论是struct{}还是[0]int 均还是false,我的goversion为:go1.18.4,我估计相关的实现方式已经修改过了)
new是一个预声明的函数,不是一个关键字。
GO-变量和指针
最新推荐文章于 2024-05-15 16:18:29 发布