变量

命名规范

通常采用驼峰式命名,当遇到特有名词(缩写或简称,如DNS)的时候,特有名词根据是否私有全部大写或小写。

形如:apiClientURLString 注意这里的 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.


此 生 无 悔 恋 真 白 ,来 世 愿 入 樱 花 庄 。