课程要点
- 了解Golang中的变量的使用
- 了解Golang中的常量的使用
- 了解变量和常量的可访问性
变量
定义变量
Golang是一门十分简约的语言,它的变量定义与其他主流语言有一定的相似之处,但是却没有像其他语言一样拥有很多可选的修饰符。
在Golang的变量定义中,我们只会用到var
这一个修饰符,并且在多数情况下var
关键字也是可以直接省略的,
从中我们也可以直观的感受到Golang设计上的简约原则。
如下所示,我们定义了一个int
类型的变量num
,因为我们没有显式进行设置初始值,所以它会拥有一个默认值0
var num int
当然,我们也可以显式的为num
变量指定合法的初始值,如下所示
var num int = 0
因为编译器可以通过我们设置的初始值自动推导出num
的数据类型为int,
所有我们也可以直接省略上述变量定义中的类型int
,简化后如下所示
var num = 0
现在是不是看着非常简洁了,那能否再进一步的对其进行简化呢,答案是当然可以的。
我们可以使用:=
来代替=
来表达声明并初始化一个变量
的语义,并且此时我们也不再需要var
关键字了。
下面就是我们定义一个变量的最简形式,也是最常用的一种定义变量的方式。
num := 0
不过值得注意的是,上述极简的变量定义方式,只能用于局部变量的定义,不能用于全局变量的声明,即全局变量必须用var
关键字进行声明。
当然,在实际的开发中,我们的程序中肯定会拥有很多个变量,Golang为我们提供了分组或者批量定义变量的方法,
可以让我们的代码更加简短,并且让逻辑更加紧凑,我们可以把一组相关的变量在同一个地方进行定义,以表达其内在关联的含义。
比如下面这段代码,我们定义了两个整型的变量,并为其指定了不同的初始值
var num1 int = 1
var num2 int = 2
我们可以使用变量分组的方式对其进行重构,这种写法在局部变量或者全局变量的定义中都是通用的。
当然与上述提到的带var
关键字的变量定义方式一样,我们可以按需省略显式的类型声明和初始化值。
var (
num1 int = 1
num2 int = 1
)
细心的同学可能会发现,上面使用分组对变量进行声明时,我们似乎不能用最后一种极简的变量定义方式来批量定义多个变量了,这难免让人感到遗憾。
所幸的是,Golang的开发者们已经考虑到了这一点,为极简方式的变量定义提供了另一种巧妙的批量声明的语法,
并且会为后续函数的多返回值声明提供强大的支持。
我们可以使用下面的极简方式批量定义多个变量,并且多个变量可以是不同类型,编译器会为我们自动推导其数据类型。
并且与定义单个变量一样,定义多个变量的方式,也只能用于局部变量的定义,不能用于全局变量的声明。
num1, num2 := 1, 2
这里将变量定义的几个方式都整理到了下面的表格中,当你遗忘时可以随时回来查看,
每个人都可以根据各自的偏好和不同的场景选择最合适的定义变量的方式。
变量定义 | 是否指定var | 是否指定类型 | 是否指定初始值 | 能否在全局中使用 |
---|---|---|---|---|
var num int | Y | Y | N | Y |
var num int = 0 | Y | Y | Y | Y |
var num = 0 | Y | N | Y | Y |
num := 0 | N | N | Y | N |
var ( num int ) |
Y | Y | N | Y |
var ( num int = 0 ) |
Y | Y | Y | Y |
var ( num = 0 ) |
Y | N | Y | Y |
num1, num2 := 1, 2 | N | N | Y | N |
未使用的局部变量
如果你在IDE中亲自动手尝试了上述的代码,会发现编译器报出了一个编译错误:num declared and not used
。
这是因为在Golang中,所有局部变量
都必须被使用过,也就是变量必须被某段代码读取过,因为如果我们从未读取过一个变量的值,
那说明这是一个无用的变量,为了保持代码的整洁,我们应该删除它。
当然,如果你是定义的全局变量
,那就不会出现这个错误,因为全局变量可能会被外部的包引用,编译器无法判定它是否永远不会被使用。
不过有时候我们出于各种不同的原因,可能就是想要在代码中保留未使用的变量,
这时我们就可以将变量赋值给_
来让编译器认为已经使用了这个变量从而忽略这个编译错误,而且它不会产生任何副作用。
_ = num
此时,我们的程序应该能成功通过编译并运行了,不过因为没有写任何逻辑代码,所以不会有任何的输出。
下面就让我们来真正的使用变量吧。
变量的使用
变量的使用十分简单,和主流的编程语言没有区别,使用上也没有什么限制,我们可以对变量进行多次读取和写入,如下面的代码所示。
// 定义int类型的变量num并初始化为0
num := 0
// 将num的值重置为1
num = 1
// 打印num的值
println(num)
// 将num的值进行加1
num++
// 再次打印num的值
println(num)
此时我们的代码可以成功编译并可以输出相应的结果了,因为我们真正的对变量进行了使用,所以成功通过了编译器的检查。
常量
常量是一种只能且必须在定义时进行初始化的变量,并且在初始化之后不能再对其进行修改。
定义常量
与变量类似,常量使用const
关键字进行定义,我们可以使用以下形式进行常量定义和初始化。
const num int = 0
当然这里我们也可以和变量定义一样省略常量的类型,因为编译器可以帮助我们推导其类型。
const num = 0
相比变量,只能使用以上两种方式定义单独的常量,因为常量必须在定义时进行显式初始化,并且需要跟变量的定义进行区分。
跟变量相同的是,上述两种常量的定义方式,也适用于常量的批量分组定义。
跟变量一节一样,这里同样在表格中对常量的定义方式进行了整理,以供查询参考。
常量定义 | 是否指定const | 是否指定类型 | 是否指定初始值 | 能否在全局中使用 |
---|---|---|---|---|
const num int = 0 | Y | Y | Y | Y |
const num = 0 | Y | N | Y | Y |
const ( num int = 0 ) |
Y | Y | Y | Y |
const ( num = 0 ) |
Y | N | Y | Y |
未使用的常量
与变量不同,未使用局部常量和全局常量都不会引发编译器的报错,不过IDE可能会建议我们删除这些未使用的常量,
是否删除完全由开发者或团队内部的编码规范等自行决定。
常量的使用
就如我们一开始所说的,常量一旦定义并初始化之后,只能被读取,无法被再次改写,否则编译器会提示报错,如下面的代码所示。
// 定义int常量num并初始化为0
const num int = 0
// 尝试将num的值重置为1会导致编译器报错:cannot assign to num (neither addressable nor a map index expression)
// num = 1
// 打印num的值
println(num)
可访问性
在Hello World的教程中,我们有提到过函数的可访问性是通过函数的首字符来判断的,全局变量和全局常量也是一样。
如果变量或者常量定义在全局之中,且变量或者常量的名称为小写字母
开头或者以_
开头,
则只有当前定义变量或者常量的包可以对其进行访问,反之则外部包都可以对其进行自由访问。
如果变量或者常量定义在某个函数体内,则只有函数体内部可以对其进行访问。
小结
通过本小节的学习,我们初步了解了Golang中变量和常量的使用,以及它们之间的一些区别。
同时,我们对Golang的简约性设计也有了一个初步的认识,后续的学习中我们会逐步体会到这一点,
让我们一起来深入探索Golang这个强大而又简洁的编程语言吧!