变量

命名规范

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

形如:apiClient、URLString

全局变量的声明与赋值

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

多变量赋值的占位符

如果函数返回多个返回值,而你只想要把其中的一个或几个赋值给相应的变量,可以使用占位符 _

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) // 常量只要类型与枚举类型一致即可,即便其值不被枚举所包括也不会报错
}

也就是说类型限制只能限制变量

参考与补充


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