go变量

语法

var name type=expression

省略

类型和表达式可以省略一个,但是不能都省略。产生了与java不一样的场景:一次声明多个不同类型的变量:

var b,f,s=true,2,3,"four"

零值

和java不太一样,似乎不只是成员变量才有0值

短变量

语法

name:=expression

重复声明等于赋值,但是短变量声明最少声明一个新变量,否责,代码编译将无法通过

in,err:=os.Open(infile)
out,err:=os.Creaqte(outfile)

生命周期

垃圾回收器如何知道一个变量是否应该被回收?

是否可达。
因为变量的生命周期是通过它是否可达来确定的,所以局部变量可在包含它的循环的一次迭代之外继续存活,即使包含它的循环已经返回,它的存在还可能延续
编译器可以选择使用堆或栈上的空间来分配,令人惊奇的是,这个选择不是基于使用var或者new关键字来声明变量
会逃逸的变量分配在堆上,不会逃逸的变量会分配在栈上。
每一次变量逃逸都需要一次额外的内存分配过程

赋值

多重赋值

允许几个变量一次性被赋值

x,y=y,x
a[i],a[j]=a[j],a[i]

从风格上考虑,如果表达式比较复杂,则避免使用多重赋值形式,一系列独立的语句更易读
还可以用来接受多返回值的函数调用结果

可赋值性

赋值只有在值对于变量类型是可赋值的时才合法
可赋值性根据类型不同有着不同的规则

类型声明

语法

type name underlying-type

类型的声明通常出现在包级别,这里命名的类型在整个包中可见,如果名字是导出的(开头使用大写字母),其他的包也可以访问它
对于每个类型T,都有一个对应的类型转换操作T(x)将值x转换为类型T。如果两个类型具有相同的底层类型或二者都是指向相同底层类型变量的未命名指针类型,则二者是可以相互转换的。类型转换不改变类型值的表达方式,仅改变类型。如果x对于类型T是可赋值的,类型转换也是允许的,但是通常是不必要的
通过==和<之类的比较操作符,命名类型的值可以与其相同类型的值或者底层类型相同的未命名类型的值比较。但是不同命名类型的值不能直接比较。

包初始化

包的初始化从初始化包级别的变量开始,这些变量按照声明顺序初始化,再依赖已解析完毕的情况下,根据依赖的顺序进行
如果包由多个.go文件组成,初始化按照编译器收到文件的顺序进行:go工具会在~~~调用编译器前~~~将.go文件进行排序

对于包级别的每一个变量,生命周期从其值被初始化开始,但是对于其他一些变量,比如数据表,初始化表达式不是简单地设置它的初始值。这种情况下,init函数的机制会比较简单,任何文件可以包含任意数量的声明如下的函数

func init() {
}

这个init函数不能被调用和引用,另一方面,它也是普通的函数。在每一个文件里,档程序启动的时候,init函数按照他们声明的顺序自动执行。
包的初始化,按照在程序中导入的顺序来进行,依赖顺序优先,每次初始化一个包,因此,如果包p导入了包q,可以确保q在p之前已完全初始化。初始化过程是自下向上的,main包最后初始化。在这种方式下,在程序的main函数开始执行前,所有的包已初始化完毕。

作用域

和java不太一样:当编译器遇到一个名字的引用时,将从最内层的封闭词法块,到全局块寻找其声明。如果在内层和外层“都存在”这个声明,内层的将先被找到。这种情况下,内层声明将“覆盖”外部声明,使它不可访问;
在包级别,声明的顺序和他们的作用域没有关系,所以一个声明可以引用它自己或者跟在它后面的其他声明,使我们可以声明递归或相互传递的类型和函数。如果常量或变量声明引用它自己,则编译器会报错。
短变量声明依赖一个明确的作用域

类型转换

通常,将某种类型的值转换成另一种,需要显式转换,对于算术和逻辑(不含位移)的二元运算符,其操作数的类型必须相同,虽然这有时会导致表达式相对冗长,但是一整类错误得以避免,程序也更容易理解

posted @ 2024-01-02 17:08  l2c  阅读(1)  评论(0编辑  收藏  举报