变量
变量作用
程序运行过程中数据是保存在内存中的,想要在代码中操作某个数据时就需要去内存上找对应的内存地址。但是,直接在代码中通过内存地址去操作数据的话,代码可读性会非常差还容易出错。所以,就利用变量将这个数据内存地址保存起来,以后直接通过这个变量就能找到内存上对应的数据了。
变量是程序为了方便地引用内存中的值而给它取的名称,本质上是给数据的内存地址起了一个好记的别名。当定义好一个变量,就会在内存中占用一片空间,至于占用多大空间,则是由数据类型来决定。
总之,变量是给程序员编程使用的。编译后,变量就没有了,换成了内存地址。因为数据在内存中访问,是靠地址来访问的。
变量声明
通过 var 关键字来声明变量,变量类型位于变量名之后。在使用变量之前,必须先声明变量。
func main() {
// var 变量名 数据类型
var a int
var b bool
fmt.Println(a, b) // 输出:0 false
}
2
3
4
5
6
变量类型相同,可在一行中声明多个变量:var a, b int
。
变量类型不同,可在 var 关键字后面使用一组小括号来声明多个变量,如下所示:
var (
a, b int
c bool
)
2
3
4
Go 的变量声明用法很清楚,只需从左到右读它们,就像在英语中一样。
变量命名规范
- 由字母、数字和下划线组成,也可以是 Unicode 字符
- 不能以数字开头
- 区分大小写
- 不能是 Go 关键字
- 尽量不要使用预定义标识符,否则后果难料
零值
在 Go 中,变量声明后没有显示初始化,会被初始化为其数据类型的默认值,称为零值(Zero values):
- 数值型:0
- 布尔型:false
- 字符串型:""
- 指针、切片、映射、函数、通道、接口:nil(所有字节的值为 0)
初始化
初始化是指在声明变量的同时为其赋予一个初始值。声明并初始化变量,可以不指定类型,因为使用具体值初始化变量时,Go 会根据初始值自动推导出其类型(动态类型声明/类型推断):
var a int = 10
var b = 20
fmt.Println(a, b) // 输出:10 20
2
3
声明和初始化多个变量,使用逗号将每个变量名称隔开:var a, b, c = 10, 20.2, "abc"
。
还可以通过另一种方式来声明和初始化变量,此方法在 Go 中最常见:empty := ""
。:=
是变量声明并初始化的简洁语法,即短变量声明。也可以使用简洁语法在一行中声明多个变量:name, age := "张三", 18
。
声明和定义
声明和定义变量并不完全一样。
声明变量:声明变量意味着在代码中引入了一个新的变量名,并指定该变量的类型。
定义变量:定义变量意味着不仅声明了变量名,还显式地对变量进行初始化。
变量赋值
变量声明后,可以使用“=”对变量进行赋值操作。
var a int
fmt.Println(a) // 输出:0
a = 10 // 赋值
fmt.Println(a) // 输出:10
a = 20 // 再次赋值
fmt.Println(a) // 输出:20
// 多重赋值
var b, c int
b, c = 20, 30
fmt.Println(b, c) // 输出:20 30
// 利用多重赋值实现两值互换
b, c = c, b
fmt.Println(b, c) // 输出:30 20
2
3
4
5
6
7
8
9
10
11
12
13
14
- 等号左边的变量,代表变量所指向的内存空间(写)
- 等号右边的变量,代表变量内存空间存储的数据值(读)
静态与强类型
前面说到,Go 是一种静态、强类型的编程语言。静态是指变量类型在编译时就已经确定,并且在编译时会检查变量类型是否与所执行操作相匹配。强类型是指变量类型是严格定义的,不允许隐式类型转换,不同类型的变量之间不能直接进行运算或赋值,需要通过显式的类型转换来实现。
func main() {
s := "hello"
s = 100 // 编译错误,不能将整型赋值给字符串变量
fmt.Println(s + 100) // 编译错误,不能将整型和字符串相加
}
2
3
4
5
类型转换
在 Go 中,只有强制类型转换,没有自动类型转换。不同类型是无法混用的,即不允许不同类型之间自动转换。
func main() {
s := 3.14
fmt.Println(int(s) + 100) // 103
}
2
3
4
类型转换时需谨慎,避免出现意想不到的错误。
func main() {
var a float64 = 32768
b := int16(a)
fmt.Println("b =", b) // b = -32768
// 通过 math 包提供的 max、min 常量,来判断是否超出 int16 范围
if a < math.MaxInt16 || a > math.MinInt16 {
fmt.Println("b is out of range of int16")
}
}
2
3
4
5
6
7
8
9
10
匿名变量
匿名变量,即没有名字的变量,用一个下划线(空标识符_
)表示,一般用于接收不需要的返回值,配合函数使用。
注意
- 匿名变量不占用命名空间,不会分配内存
- 匿名变量的值不能被访问,因为它没有实际的存储位置
- 匿名变量不能出现在表达式中,因为它没有实际值
注意事项
- 变量须先声明才能使用,且不能重复声明
- 变量声明类型和初始化类型必须一致
- 局部变量声明后必须使用,全局变量可以声明不使用
:=
短变量声明,只能在函数内使用,不能在包内使用:=
短变量声明,至少保证有一个是新变量且在同一作用域,旧变量退化为初始化操作
小拓展
注释
在编码过程中,注释必不可少,Go 支持两种注释格式:
- 单行注释:以双斜杠
//
开始,直到行尾为止 - 多行注释:以
/*
开头,以*/
结尾,可以跨越多行
特殊注释:
- TODO:将来要完成,推荐使用
- NOTE:提供额外的说明或重要信息,引人注意
- Deprecated:告知已经过期,建议不要使用。将来某个版本可能移除
注释快捷键:
- VS Code 单行注释快捷键:
Ctrl + /
- VS Code 多行注释快捷键:
Shift + Alt + a
关键字
关键字是 Go 内置的标识符,这些标识符已经有固定含义了,在给变量起名字时就不能再使用这些关键字了。
在 Go 中,有 25 个关键字是保留的,不能用作标识符:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
2
3
4
5
预定义标识符
Types:
any bool byte comparable
complex64 complex128 error float32 float64
int int8 int16 int32 int64 rune string
uint uint8 uint16 uint32 uint64 uintptr
Constants:
true false iota
Zero value:
nil
Functions:
append cap clear close complex copy delete imag len
make max min new panic print println real recover
2
3
4
5
6
7
8
9
10
11
12
13
14
15