变量
命名规范
通常采用驼峰式命名,当遇到特有名词(缩写或简称,如DNS)的时候,特有名词根据是否私有全部大写或小写。
形如:apiClient
、URLString
注意这里的 api
(全小写) 和 URL
(全大写)
全局变量的声明与赋值
package main
import "fmt"
// 指定类型的变量声明:如果没有为变量赋值,就需要指定变量的类型
var a,b,c int
// 变量赋值会自动匹配类型,无需指定
var d = 1 // 等同于 var d int = 1
// 一次赋值多个变量
var e,f,g = 1,2,3
// 变量代码块
var (
h = 4
i = 5
j,k = 6,7
)
func main(){
...
}
局部变量的声明与赋值
package main
import "fmt"
func main(){
// 除了上面讲到的声明方式外,函数体内可以通过更简单的方式定义临时变量
a := 6
// 也可以一次多定义几个
b,c := 8,10
// 声明的局部变量如果没被使用就会报错
fmt.Println(a,b,c)// 输出结果 6,8,10
}
**注意:**如果变量类型不足以存储变量值会导致溢出错误
var num byte = 1000000 // overflows
多变量赋值
多变量赋值时,先计算所有相关值,然后再从左到右依次赋值
看下面代码
package main
import "fmt"
func main() {
data, i := [3]int{1,2,3},0
i,data[i] = 2,5
fmt.Println(data,i,data[i])// 输出结果:[5 2 3] 2 3
}
问:为什么不是输出 [1,2,5] 2 3 ?
答:先计算,后赋值,data[i]中的i被当作0看待
即i,data[i] = 2, 5
当作i,data[0] = 2,5
因此,如果你想交换两个元素的值就变得非常简单了
//交换i和j的值
i,j := j,i
多变量赋值的占位符
如果函数返回多个返回值,而你只想要把其中的一个或几个赋值给相应的变量,可以使用占位符 _
package main
import "fmt"
// 指定方法的返回类型
func test() (int, string) {
return 1, "abc"
}
func main() {
_, s := test()
fmt.Println(s)// s获取到test()的第二个返回值,输出abc
}
同名变量的优先级
同java相同,作用域越小的变量优先级就越高
package main
import "fmt"
var num = 1
func main() {
fmt.Println(num)// 使用全局变量,输出1
num := 2
fmt.Println(num)// 使用main中的局部变量,输出2
{
num := 3
fmt.Println(num)// 使用代码块中的局部变量,输出3
}
}
常量
常量值 必须是编译器可确定的 数字、字符串、布尔值。
这意味着,常量必须在声明的时候初始化
命名规范
同变量规则,力求语义表达完整清楚,不要嫌名字长。
如果模块复杂,为避免混淆,可按功能统一定义在package下的一个文件中。
通常也使用驼峰命名法
常量与常量组的声明
const x, y int = 1, 2 // 多常量初始化
const s = "Hello, World!" // 类型推断
const ( // 常量组
a, b = 10, 100
c bool = false
d //如果不提供类型和初始化值则视为和上一常量相同,即 d = false
//常量值可以使用len、cap、unsafe.Sizeof等编译器可确定的函数返回值
e = len(a)
f = unsafe.Sizeof(b)
)
func main() {
const x = "xxx" // 未使⽤用局部常量不会引发编译错误。
}
**注意:**如果常量类型不足以存储变量值会导致溢出错误
const num byte = 1000000 // overflows
枚举
枚举其实就是一个带自增特性的常量组,而这个自增特性是通过关键字 iota
实现的。
iota是golang语言的常量计数器,只能在常量的表达式中使用。
iota 定义常量组中从 0 开始按行计数的自增枚举值。
const (
Sunday = iota // 0
Monday // 1,通常省略后续⾏行表达式。
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
由于常量赋值是可以用编译器能解释的计算式表达的,所以就出现了下面的骚操作
const (
_ = iota // iota = 0
KB int64 = 1 << (10 * iota) // iota = 1
MB // 与 KB 表达式相同,但 iota = 2
GB // 同上,但 iota = 3
TB // 同上,但 iota = 4
)
上述方式在用于表达具有数量级关系的枚举时特别有用
多个iota的各自增长
在同一常量组中,可以提供多个 iota,它们各自增长,互不影响。
const (
A, B = iota, iota << 10 // 0, 0 << 10
C, D // 1, 1 << 10
)
**技巧:**一列一列的看,同一列上的枚举项共用计数器 iota
自增中出现显示赋值
const (
A = iota // 0
B // 1
C = "c" // c
D // c,与上⼀一⾏行相同。
E = iota // 4,显式恢复。注意计数包含了 C、D 两⾏行。
F // 5
)
通过自定义类型实现枚举类型限制
package main
import "fmt"
// 声明一种叫Color的类型,其本质是一个int
type Color int
const (
Black Color = iota // 定义一个Color类型的枚举项
Red // ...
Blue // ...
)
//必须传入枚举类型Color的函数
func test(c Color) {
fmt.Println(c)
}
func main() {
c := Black
test(c) //输出0
x := 1
test(x) // Error: cannot use x (type int) as type Color in function argument
test(1) // 常量会被编译器自动转换,不会报错
test(10) // 常量只要类型与枚举类型一致即可,即便其值不被枚举所包括也不会报错
const numd = 10
test(numd) // 常量只要类型与枚举类型一致即可,即便其值不被枚举所包括也不会报错
}
也就是说类型限制只能限制变量
参考与补充
Q.E.D.