[Effective Go 中文翻译] Initialization篇

Posted 凌星An

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Effective Go 中文翻译] Initialization篇相关的知识,希望对你有一定的参考价值。

即使Go中的初始化和C/C++中的十分类似,但是Go中更加强大。可以在初始化期间构造复杂的结构,可以正确处理 初始化对象的 调用顺序,即使是不同包之间的初始化,也能够正确处理。

Constants

常量(包含定义在函数内部的局部常量)会在编译期间被创建,只能是数字、字符(runes)、字符串 或者布尔类型。因为编译期间的限制,定义它们的表达式必须是常量表达式,能被编译器计算。
比如:1<<3 是一个常量表达式。而math.Sin(math.Pi/4) 不是,因为 调用math.Sin()函数发生的 运行时期。

在Go中,枚举常量可以使用itoa 枚举器来创建。因为itoa是表达式的一部分 并且表达式可以隐式重复 。它可以创建一系列复杂的值。

eg:

type ByteSize float64

const (
    _           = iota // ignore first value by assigning to blank identifier
    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.09TB

这里使用Sprintf实现ByteSize的String方法是安全的(不会导致递归调用) 。因为Sprintf 使用了%f,%f不是需要一个string值 。Sprintf仅会在需要一个string的时候才会调用String方法,而%f是需要一个浮点类型的值。

Variables

变量像常量一样被初始化,但可以是一个在运行期间计算的表达式。
eg:

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

The init function

finally, 每个源文件都会定义它自己的init函数来设置需要的状态(每个源文件可能由多个init函数) 。finally 的意思是,包内的init函数 会在 包内所有变量被它们的初始化器初始化 并且,所有导入的包被初始化后 进行调用。

除了不能用声明表示的初始化之外,init函数的一个常见用途是在真正开始执行之前验证或修复程序状态的正确性。

func init() 
    if user == "" 
        log.Fatal("$USER not set")
    
    if home == "" 
        home = "/home/" + user
    
    if gopath == "" 
        gopath = home + "/go"
    
    // gopath may be overridden by --gopath flag on command line.
    flag.StringVar(&gopath, "gopath", gopath, "override default GOPATH")

创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖

以上是关于[Effective Go 中文翻译] Initialization篇的主要内容,如果未能解决你的问题,请参考以下文章

[Effective Go 中文翻译]函数篇

[Effective Go 中文翻译] Initialization篇

Effective Go中文版(更新中)

Effective Go - The Go Programming Language

Effective Python 中文版

《effective Go》读后记录