go基础01-变量声明:静态语言有别于动态语言的重要特征

129 阅读3分钟

go语言变量声明方法

image.png

这个变量声明4个部分:

  • var 是修饰变量声明的关键字;
  • a 为变量名;
  • int 为该变量的类型;
  • 10 是变量的初值。

如果没有为这个变量赋予初始值,go编译器会为这个变量赋予类型的零值。 除了单独声明每个变量外,Go 语言还提供了变量声明块(block)的语法形式,可以用一个 var 关键字将多个变量声明放在一起,像下面代码这样:

var (
    a int = 128
    b int8 = 6
    s string = "hello"
    c rune = 'A'
    t bool = true
)

Go 语言还提供了两种变量声明的“语法糖”。

省略类型信息的声明:

在通用的变量声明的基础上,Go 编译器允许我们省略变量声明中的类型信息,它的标准范式是“var varName = initExpression”,比如下面就是一个省略了类型信息的变量声明:

var b = 13

显然这种省略类型信息声明的“语法糖”仅适用于在变量声明的同时显式赋予变量初值的情况,下面这种没有初值的声明形式是不被允许的:

var b

结合多变量声明,我们可以使用这种变量声明“语法糖”声明多个不同类型的变量:

//第一种:
plain
var a = 13 // 使用默认类型
var b int32 = 17  // 显式指定类型
var f float32 = 3.14 // 显式指定类型

//第二种:
var a = 13 // 使用默认类型
var b = int32(17) // 显式指定类型
var f = float32(3.14) // 显式指定类型
var a, b, c = 12, 'A', "hello"

短变量声明:

a := 12
b := 'A'
c := "hello"

而且,短变量声明也支持一次声明多个变量,而且形式更为简洁,是这个样子的:

a, b, c := 12, 'A', "hello"

不过呢,短变量声明的使用也是有约束的,并不是所有变量都能用短变量声明来声明的,这个你会在下面的讲解中了解到。

Go 语言的两类变量

通常来说,Go 语言的变量可以分为两类:一类称为包级变量 (package varible),也就是在包级别可见的变量。如果是导出变量(大写字母开头),那么这个包级变量也可以被视为全局变量;另一类则是局部变量 (local varible),也就是 Go 函数或方法体内声明的变量,仅在函数或方法体内可见。而我们声明的所有变量都逃不开这两种。

包级变量的声明形式

包级变量只能使用带有 var 关键字的变量声明形式,不能使用短变量声明形式,但在形式细节上可以有一定灵活度。

第一类:声明并同时显式初始化。

// $GOROOT/src/io/io.go
var ErrShortWrite = errors.New("short write")
var ErrShortBuffer = errors.New("short buffer")
var EOF = errors.New("EOF")

当然,如果我们不接受默认类型,而是要显式地为包级变量指定类型,那么我们有两种方式,我这里给出了两种包级变量的声明形式的对比示例。

//第一种:
plain
var a = 13 // 使用默认类型
var b int32 = 17  // 显式指定类型
var f float32 = 3.14 // 显式指定类型

//第二种:
var a = 13 // 使用默认类型
var b = int32(17) // 显式指定类型
var f = float32(3.14) // 显式指定类型

虽然这两种方式都是可以使用的,但从声明一致性的角度出发,Go 更推荐我们使用后者,这样能统一接受默认类型和显式指定类型这两种声明形式,尤其是在将这些变量放在一个 var 块中声明时,你会更明显地看到这一点。

第二类:声明但延迟初始化。

var a int32
var f float64

局部变量的声明形式

第一类:对于延迟初始化的局部变量声明,我们采用通用的变量声明形式


var err error

第二类:对于声明且显式初始化的局部变量,建议使用短变量声明形式

a := 17
f := 3.14
s := "hello, gopher!"

对于不接受默认类型的变量,我们依然可以使用短变量声明形式,只是在":="右侧要做一个显式转型,以保持声明的一致性:

a := int32(17)
f := float32(3.14)
s := []byte("hello, gopher!")

这里我们还要注意:尽量在分支控制时使用短变量声明形式。

// $GOROOT/src/strings/strings.go
func LastIndexAny(s, chars string) int {
    if chars == "" {
        // Avoid scanning all of s.
        return -1
    }
    if len(s) > 8 {
        // 作者注:在if条件控制语句中使用短变量声明形式声明了if代码块中要使用的变量as和isASCII
        if as, isASCII := makeASCIISet(chars); isASCII { 
            for i := len(s) - 1; i >= 0; i-- {
                if as.contains(s[i]) {
                    return i
                }
            }
            return -1
        }
    }
    for i := len(s); i > 0; { 
        // 作者注:在for循环控制语句中使用短变量声明形式声明了for代码块中要使用的变量c
        r, size := utf8.DecodeLastRuneInString(s[:i])
        i -= size
        for _, c := range chars {
            if r == c {
                return i
            }
        }
    }
    return -1
}

小结

在这一讲中,我们学习了多种 Go 变量声明的方法,还学习了不同类型 Go 变量可以采用的变量声明形式和惯用法,以及一些变量声明的最佳实践原则。具体来说,Go 语言提供了一种通用变量声明形式以及两种变量声明“语法糖”形式,而且 Go 包级变量和局部变量会根据具体情况选择不同的变量声明形式,这里我们用一幅图来做个形象化的小结:

image.png

此文章为3月Day1学习笔记,内容来源于极客时间《Tony Bai · Go 语言第一课》,对于小白推荐该课程。