此篇文章是我参与 #青训营笔记创作活动 的第9篇笔记
主要是简单记录一下自己在学习Go语言基础语法中的变量部分时遇到的一些小要点,
只是个人的一个学习记录,水平不高还望大佬们包容。
0x01 变量的声明
声明变量的一般形式是使用 var 关键字:
var name type
- var 是声明变量的关键字,name 是变量名,type 是变量的类型
- var 变量名 变量类型
- 行尾无须分号
- 声明变量时将变量的类型放在变量的名称
- 避免像C语言中那样含糊不清的声明形式,例如:
int* a, b;。其中 a 是 int 指针,而 b 是 int 类型的变量 - 如果你想要这两个变量都是指针,则需要将它们分开书写
- 避免像C语言中那样含糊不清的声明形式,例如:
- 变量的基本类型
- bool
- string
- int、int8、int16、int32、int64
- uint、uint8、uint16、uint32、uint64、uintptr
- byte
- uint8 的别名
- rune
- int32 的别名 代表一个 Unicode 码
- float32、float64
- complex64、complex128(复数)
complex64中实部和虚部是32位的,在complex128中实部和虚部是64位的
批量格式
-
可以用括号来进行批量声明变量
-
var ( a int b string c []float32 d func() bool e struct { x int } )
简短格式
-
名字 := 表达式
-
i, j := 0, 1 -
需要注意的是,简短模式(short variable declaration)有以下限制:
- 定义变量,同时显式初始化
- 不能提供数据类型
- 只能用在函数内部
0x02 变量的初始化
当一个变量被声明之后,系统自动赋予它该类型的零值
- 整型和浮点型变量的默认值为 0 和 0.0
- 字符串变量的默认值为空字符串
- 布尔型变量默认为 bool
- 切片、函数、指针变量的默认为 nil
所有的内存在 Go 中都是经过初始化的
当然,我们依然可以在变量声明时赋予变量一个初始值。
回顾C语言:
在C语言中,变量在声明时,并不会对变量对应内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在使用C语言进行声明时要初始化操作,稍有不慎,就会造成不可预知的后果。
在网络上只有程序员才能看懂的“烫烫烫”和“屯屯屯”的梗,就来源于 C/C++ 中变量默认不初始化。
微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字。
因此,如果一个字符串没有结束符
\0,直接输出的内存数据转换为字符串就刚好对应“烫烫烫”和“屯屯屯”。
初始化的标准格式
var 变量名 类型 = 表达式
- 在标准格式的基础上,将 int 省略后,编译器会尝试根据等号右边的表达式推导变量的类型
- 等号右边的部分在编译原理里被称做右值(rvalue)
初始化的简短格式
变量名 := 表达式
-
编译器会自动根据右值类型推断出左值的对应类型
-
由于使用了
:=,而不是赋值的=,因此推导声明写法的左值变量必须是没有定义过的变量- 若定义过,将会发生编译错误
-
在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错
-
a, b := 1, 2 a, c := 1, 3
-
变量交换
- 中间变量交换法
- temp = a
- a = b
- b = temp
- 加减交换法
- a = a + b
- b = a - b
- a = a - b
- 注意:
- 不能交换非数字类型的变量
- 对于浮点类型的变量可能会出现问题
- 加法过程中可能会出现超出上限的问题
- 异或交换法
- a = a ^ b
- b= a ^ b
- a = a ^ b
- 注意:
- 只能用于交换可以进行异或运算的数据类型
- 如果 a , b 指向同一个内存地址,则异或交换法失效
- “多重赋值” 变量交换法
- b, a = a, b
- 利用 Go 语言的“多重赋值”特性(其实python也可以用这个方法来交换变量)
- 多重赋值时,变量的左值和右值按从左到右的顺序赋值
0x03 匿名变量
在编码过程中,可能会遇到没有名称的变量、类型或方法。虽然这不是必须的,但有时候这样做可以极大地增强代码的灵活性,这些变量被统称为匿名变量。
在 Lua 等编程语言里,匿名变量也被叫做哑元变量
-
匿名变量的特点是一个下画线
__本身就是一个特殊的标识符,被称为空白标识符
-
它可以像其他标识符那样用于变量的声明或赋值
- 任何类型都可以赋值
-
不可后续使用
- 任何赋给这个标识符的值都将被抛弃
- 因此这些值不能在后续的代码中使用
- 也不可以使用这个标识符作为变量对其它变量进行赋值或运算。
-
使用匿名变量时,只需要在变量声明的地方使用下画线替换即可
-
_ , a:= 1, 2
-
-
不占用内存空间
- 匿名变量不占用内存空间,不会分配内存
-
可多次声明
- 匿名变量与匿名变量之间也不会因为多次声明而无法使用
0x04 作用域
根据变量定义位置的不同,可以分为以下三个类型:
- 局部变量
- 函数内定义的变量
- 作用域只在函数体内,函数的参数和返回值变量都属于局部变量
- 函数调用结束后局部变量就会被销毁
- 全局变量
- 函数外定义的变量
- 全局变量只需要在一个源文件中定义,就可以在所有源文件中使用
- 不包含这个全局变量的源文件需要使用“import”关键字引入全局变量所在的源文件之后才能使用这个全局变量
- 形式参数
- 函数定义中的变量
- 在定义函数时函数名后面括号中的变量叫做形式参数(简称形参)
- 形式参数只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。
- 函数定义中的变量
附录
本文参考链接及推荐阅读: