变量和常量
值类型和引用类型
Go中, 大部分的变量都是值类型的. 包括基本数据类型, 如整型, 浮点型, 布尔型等, 也包括复合数据类型, 如数组, 结构体等. 简单的说, 就是你将一个变量赋值给另一个变量的时候, 或者将一个变量作为参数传递给函数的时候, 实际上传递的是这个变量的副本, 而不是引用.
例子
以下是基本数据类型, 和Python一样, 都是值类型的:
var a int = 10
var b int = a
b = 5
fmt.Println(a) // 10
fmt.Println(b) // 5
以下是复合数据类型数组, 这个时候就反直觉了:
var lis1 [5]int = [5]int{1, 2, 3, 4, 5}
var lis2 [5]int = lis1
lis2[0] = 20
fmt.Println(lis1[0]) // 1
fmt.Println(lis2[0]) // 20
在Python中, 这两个打印的都应该是20
.
当然, Go语言也提供了指针, 允许通过指针来访问和修改变量的值. 当你使用指针的时候, 你可以直接修改原始变量, 而不是修改副本. 此外, Go中的切片, 映射, 通道, 这些复合类型的实现本质上是包含了一个指向底层数组或数据结构的指针. 这些类型是引用类型, 即在赋值的时候, 仍然是创建了一个新的副本, 但是这个副本里面的指针是不会改变的, 所以可以影响原始数据, 实现了引用的效果.
变量
Go是一种强类型语言, 意味着每个变量必须经过类型声明才可以进行使用.同一作用域内不支持重复声明.
Go语言的变量声明格式为:
var <name> <type>
警告
全局变量声明不能省略var
, 局部变量声明可以省略var
.
批量声明
每声明一个变量就需要写一个var
会比较繁琐, Go还支持批量变量声明.
例子
var (
a string
b int
c bool
d float32
)
变量初始化
Go语言在声明变量的时候, 会自动对变量对应的内存区域进行初始化操作. 每个变量会被初始化成其类型的默认值. 如, 整型和浮点型变来概念的默认值为0
, 字符串变量的默认值为空字符串. 布尔类型变量的默认值为false
. 切片, 函数, 指针变量的默认值为null
.
当然, 我们也可以在声明变量的时候为其指定初始值:
var <name> <type> = <expression>
类型推导
有时候我们会将变量的类型省略, 这个时候编译器会根据等号右边的值来推导变量的类型完成初始化.
例子
var name = "ricolxwz"
var sex = 1
短变量声明
在函数内部, 可以使用更简单的:=
的方式声明并初始化变量.
例子
func main() {
n := 10
m := 20
}
警告
- 使用短变量声明无法显式指定类型
- 不能在函数外使用短变量声明
- 在块内, 短变量声明不仅可以用于声明, 还可以用于已经存在的变量被赋予新值
匿名变量
详情见下划线.
常量
常量是恒定不变的值.
常量初始化
常量定义的时候必须赋值.
例子
const pi = 3.1415
批量初始化
例子
const (
pi = 3.1415
e = 2.7182
)
提示
在批量初始化中, 若省略了值则表示和上面一行的值相同:
例子
const (
n1 = 100
n2
n3
)
iota
iota
是Go语言的常量计数器, 只能在常量的表达式中使用. iota
在const
关键字出现的时候被重置为0
. const
声明中每增加一行常量声明将会使iota
计数一次.
EXAMPLE
一个基础的例子:
const (
n1 = iota //0
n2 //1
n3 //2
n4 //3
)
可以使用_
跳过某些值:
const (
n1 = iota //0
n2 //1
_
n4 //3
)
中间还可以插队:
const (
n1 = iota //0
n2 = 100 //100
n3 = iota //2
n4 //3
)
const n5 = iota //0
作用域
Go语言变量和常量的作用域主要有全局和局部两种.
- 全局作用域: 若变量/常量声明在在当前文件的最外层, 则为全局变量/常量
- 局部作用域: 若变量/常量明在函数内/块内, 则为局部变量常量/常量
警告
全局变量/常量可以在整个包内使用, 即a.go中定义个全局变量/常量能直接在b.go中使用, 只要a.go和b.go属于同一个包. 这不同于Python, Python中一个模块(即一个文件)的全局变量/常量要在另一个模块使用, 需要用import
导入.