对别人的意见要表示尊重。千万别说:"你错了。"——卡耐基
温馨提示:本文适合具有一定编程基础的童鞋阅读。
变量定义方式
变量名在运行时是不存在的,运行时直接操作内存地址。
未使用的局部变量,会被编译器认为是错误的,全局变量没事。
单个变量的定义
var x int # 自动初始化为0var y = false # 自动推断类型
多个变量的定义
先计算右值,然后菜赋值:
var x,y intvar a, s = 100, "abc"# 组的方式var ( x, y int a, s = 100, "abc")
简短模式
简短模式的限制:
- 只能用在函数内部
- 定义变量,同时显示初始化
- 不能提供数据类型
- 多返回值时,有部分会退化为赋值操作
func main() { x := 100 a, s := 1, "abc"}
错误使用情况:
var x = 100func main() { x := "abc" // 实际是重新定义和初始了同名局部变量}
简短模式在函数多返回值,if/for/switch 中定义局部变量 很方便
多返回值时(必须至少一个是新定义的),有部分会退化为赋值操作:
func main(){ x := 100 x, y := 200, "abc" // 这里x 为赋值操作 z := 100 z := 200 // 会报错的 { x, y :=200,300 // 不同作用域,全部是新定义 } // 下面重复使用err很有意义 f,err := os.Open("/dev") n,err := f.Read(buf)}
变量命名
特别之处
符合首字母大小写决定了其作用域:
- 首字母大写的为导出成员,可被包外引用
- 首字母小写的仅能在包内使用
空标识符
“—” 标识忽略占位符使用,作为表达式左值,无法读取内容。
x, _ := f.read(buf) // _ 标识忽略err
通常用来避免 编译器对“未使用变量” 和 “导入包” 的错误检查
常量
常量在编译器编译后,作为指令数据使用,不会像变量一样分配存储空间,所以不能取地址
不可变,未使用也不会引发编译器错误
- 可以是计算出结果的表达式
- 后一行未指定初始值,则和上一行非空常量值相同
const x, y int = 123,332const s = "ewew"const ( i, f = 1, 0.123 b = false s = "221" z // 等于 221)func main() { const x = 123 { const x = "abs" // 不同作用域定义同名变量 }}
枚举
go并没有提供枚举enum。可借助iota
const ( x = iota // 0 y // 1 z // 2 )
基本数据类型
通过math.MinInt8, math.MaxInt8 可以看到各种类型取值范围。
别名,可以直接替换的只有2个:
- byte 是 uint8
- rune s int32
引用类型
特指 slice, map, channel 这三种预定义类型
- 必须使用make函数创建,完成内存分配和相关属性初始化
s := make([]int, 0, 10) // slices = append(s, 100)m := make(map[string]int) // mapm["a"] = 1
类型转换
- 必须是显示的类型转换
- 不能将非bool类型的当作true ,false
a := 10b := byte(a)c := a + int(b)
自定义类型
基于现有的基础类型,或者结构体等
user struct { name string age uint8}