初始化

未匹配的标注

尽管从表面上看,Go 的初始化过程与 C 或 C++ 差别并不算太大,但它确实更为强大。 在初始化过程中,不仅可以构建复杂的结构,还能正确处理不同包对象间的初始化顺序。

常量

Go 中的常量就是不变量。它们在编译时创建,即便它们可能是函数中定义的局部变量。 常量只能是数字、字符(符文)、字符串或布尔值。由于编译时的限制, 定义它们的表达式必须也是可被编译器求值的常量表达式。例如 1<<3 就是一个常量表达式,而 math.Sin(math.Pi/4) 则不是,因为对 math.Sin 的函数调用在运行时才会发生。

在Go中,枚举常量使用枚举器 iota 创建。由于 iota 可为表达式的一部分,而表达式可以被隐式地重复,这样也就更容易构建复杂的值的集合了。

type ByteSize float64

const (
    _           = iota // 通过赋予空白标识符来忽略第一个值
    KB ByteSize = 1 << (10 * iota)
    MB
    GB
    TB
    PB
    EB
    ZB
    YB
)

由于可将 String 之类的方法附加在用户定义的类型上, 因此它就为打印时自动格式化任意值提供了可能性,即便是作为一个通用类型的一部分。 尽管你常常会看到这种技术应用于结构体,但它对于像 ByteSize 之类的浮点数标量等类型也是有用的。

func (b ByteSize) String() string {
    switch {
    case b >= YB:
        return fmt.Sprintf("%.2fYB", b/YB)
    case b >= ZB:
        return fmt.Sprintf("%.2fZB", b/ZB)
    case b >= EB:
        return fmt.Sprintf("%.2fEB", b/EB)
    case b >= PB:
        return fmt.Sprintf("%.2fPB", b/PB)
    case b >= TB:
        return fmt.Sprintf("%.2fTB", b/TB)
    case b >= GB:
        return fmt.Sprintf("%.2fGB", b/GB)
    case b >= MB:
        return fmt.Sprintf("%.2fMB", b/MB)
    case b >= KB:
        return fmt.Sprintf("%.2fKB", b/KB)
    }
    return fmt.Sprintf("%.2fB", b)
}

表达式 YB 会打印出 1.00YB,而 ByteSize(1e13) 则会打印出 9.09

在这里用 Sprintf 实现 ByteSizeString 方法很安全(不会无限递归),这倒不是因为类型转换,而是它以 %f 调用了 Sprintf,它并不是一种字符串格式:Sprintf 只会在它需要字符串时才调用 String 方法,而 %f 需要一个浮点数值。

变量

变量能像常量一样初始化,而且可以初始化为一个可在运行时得出结果的普通表达式。

var (
    home   = os.Getenv("HOME")
    user   = os.Getenv("USER")
    gopath = os.Getenv("GOPATH")
)

init 函数

最后,每个源文件都可以通过定义自己的无参数 init 函数来设置一些必要的状态。 (其实每个文件都可以拥有多个 init 函数。)而它的结束就意味着初始化结束: 只有该包中的所有变量声明都通过它们的初始化器求值后 init 才会被调用, 而包中的变量只有在所有已导入的包都被初始化后才会被求值。

除了那些不能被表示成声明的初始化外,init 函数还常被用在程序真正开始执行前,检验或校正程序的状态。

func init() {
    if user == "" {
        log.Fatal("$USER not set")
    }
    if home == "" {
        home = "/home/" + user
    }
    if gopath == "" {
        gopath = home + "/go"
    }
    // gopath 可通过命令行中的 --gopath 标记覆盖掉。
    flag.StringVar(&gopath, "gopath", gopath, "override default GOPATH")
}

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/effective-go/20...

译文地址:https://learnku.com/docs/effective-go/20...

上一篇 下一篇
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~