Course2
变量
使用var关键词一次定义多个变量,变量名在前,类型在后,声明时不初始化会默认初始化为二进制0值,如果提供初始化值,可以省略类型,由编译器推断。可以多行变量定义
var(
x,y int
a,s=100,"abc"
)
简短模式
func main() {
x := 100
a, s := 1, "abc"
-
- 定义变量,同时显式初始化。
- 不能提供数据类型。
- 只能用在函数内部。
简短定义在函数多返回值,以及 if/for/switch 等语句中定义局部变量非常方便。
退化赋值
在同一作用域下赋值的多个变量中至少有一个新变量时,不生成新的旧变量
多变量赋值
首先计算所有右值再依次赋值
x, y := 1, 2 x, y = y+3, x+2
未使用错误
在go中未使用的局部变量会被认为是错误
变量命名建议
- 以字母或下画线开始,由多个字母、数字和下画线组合而成。
- 区分大小写。
- 使用驼峰(camel case)拼写格式。
- 局部变量优先使用短名。
- 不要使用保留关键字。
- 不建议使用与预定义常量、类型、内置函数相同的名字。
- 专有名词通常会全部大写,例如 escapeHTML。
- 尽管 Go 支持用汉字等 Unicode 字符命名,但从编程习惯上来说,这并不是好选择
- 符号名字首字母大小写决定了其作用域。首字母大写的为导出成员,可被包外引用,而 小写则仅能在包内使用。
- Go源代码中有大量单字母、单个词或缩写命名的简短命名变量,通过保持一致性来维持可读性。
- i index
- k key
- v value
- e elem
- r range
- t time
- b byte
空标识符
和python类似的go中也有个 “ _ ” 的特殊成员,用于忽略占位符使用,临时规避未使用变量和导入包的错误检查
常量
使用const定义常量值,不支持C++中的数字类型后缀,
- 不使用的常量不会编译错误
- 常量值可以使用被编译器能计算的结果,如unsafe.Sizeof, len, cap等方法
- 在常量组中如果不指定类型和值,则与上一行中的相同
const( x unint16 =120 y s ="abc" z )
枚举与iota
- go 中没有明确定义enum,可以使用iota标识符实现自增常量实现枚举类型
- 可以使用空标识符占位
- 在多常量定义中使用多个iota,各自单独计数,要求每行的列数相同
- 中断iota自增,必须显式恢复,且后续自增值按行顺序递增,而非按上一个取值递增
- 默认类型为int,可以显式指定类型,
- 建议使用自定义类型实现用途明确的枚举类型
基本类型
![[../images/Pasted image 20220919103451.png]]![[../images/Pasted image 20220919103502.png]]
- 标准库 math 定义了各数字类型的取值范围
- 标准库 strconv 可在不同进制(字符串)间转换。
a, _ := strconv.ParseInt("1100100", 2, 32
别名
在官方的语言规范中,专门提到两个别名。
byte alias for uint8 rune alias for int32
别名类型无须转换,可直接赋值。
引用类型
特指slice,map,channel,必须使用make函数而非new,因为new不关心内部构造和初始化方法,仅仅按照类型分配初始化的空间,因此new map是无法正常工作的。make会被编译器转换为目标i类型专用的创建函数。也可以使用初始化表达式
类型转换
go中禁止大部分隐式类型转换
- 不能将非bool类型当作bool用
- 如果转换的目标是指针,单向通道,无返回值的函数,必须使用括号
自定义类型
使用关键字type基于现有基础类型(包括结构体和函数)定义自定义类型 。 即便指定了基础类型,也只表明它们有相同底层数据结构,两者间不存在任何关系,属 完全不同的两种类型。除操作符外,自定义类型不会继承基础类型的其他信息(包括方 法)。不能视作别名,不能隐式转换,不能直接用于比较表达式。
未命名类型
与有明确标识符的 bool、int、string 等类型相比,数组、切片、字典、通道等类型与具 体元素类型或长度等属性有关,故称作未命名类型(unnamed type)。当然,可用 type 为其提供具体名称,将其改变为命名类型(named type)
表达式
流程控制
if else
- 所有流程控制语句都可以在头部放一行初始化语句,这个语句编译之后会变成代码块里的隐式代码块
- if else多个嵌套,作用域嵌套,高层无法访问低层
- if的快乐路径原则
- 首先判断错误,如果错误,快速返回
- 所有错误路径都判断错误之后,剩下的就是成功路径,所以说成功逻辑不放在if中
- 成功逻辑在最后一句
switch
```go switch{ case: case: default:
- ```
- 条件表达式不要求为整型
- case不用break,不会fallthrough
- 使用没有条件的switch比并列的if-else更清晰
- 可以显式使用fallthrough
- 惰性求值:
- 满足条件直接结束,剩下的case语句都不执行
- fallthrough之后,当前的case剩下的都不执行
- 从上到下,从左到右
for
- 没有while,只有一个条件判断语句的时候,相当于while
- 三个语句省略的时候不能不加分号
break,goto和continue
- 跳出一层循环和直接进入下一次循环
- go语言支持转移语句,
break label
、goto label
跳转到指定的循环层,goto的意义或许只是语义更加清晰
课堂练习
对于字符串而言,切片返回的字符数组切片,但是下标访问的确是字节数组
内置函数
切片x[low,high,max],len=high-low,cap=max-low len cap append