博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[翻译] effective go 之 Initialization
阅读量:6430 次
发布时间:2019-06-23

本文共 4202 字,大约阅读时间需要 14 分钟。

hot3.png

Initialization

Although it doesn't look superficially very different from initialization in C or C++, initialization in Go is more powerful. Complex structures can be built during initialization and the ordering issues between initialized objects in different packages are handled correctly.

从表面上看 Go的初始化和C/C++区别不大 但是Go更加给力 复杂的数据结构可以在初始化的时候建立起来 并且Go可以准确地处理不同包之间的对象初始化顺序

Constants 常量初始化

Constants in Go are just that—constant. They are created at compile time, even when defined as locals in functions, and can only be numbers, strings or booleans. Because of the compile-time restriction, the expressions that define them must be constant expressions, evaluatable by the compiler. For instance, 1<<3 is a constant expression, while math.Sin(math.Pi/4) is not because the function call to math.Sin needs to happen at run time.

Go中的常量在编译的时候创建 即使变量是定义在函数内的局部变量 也是在编译过程中搞定 常量只可以是数字 字符串 或者布尔值  受限于这个条件 常量表达式必须是可以被编译器推导出的 举例来说1<<3 是常量表达式 而math.Sin(math.Pi/4)就不是常量表达式 因为这里涉及到了函数调用 这个是在运行时才进行计算的

In Go, enumerated constants are created using the iota enumerator. Since iota can be part of an expression and expressions can be implicitly repeated, it is easy to build intricate sets of values.

Go中的枚举常量 可以通过iota来创建 由于iota可以是表达式的一部分 而且表达式可以被重复 可以很容易地创建复杂的数据集 每一个const关键字出现时 iota会被重置为0 iota会在下一次引用时自动+1 当const赋值表达式相同时可省略之后的赋值表达式 下面的这个例子的赋值表达式就省略了 统一为 1<<(10*iota)

type ByteSize float64const (    _           = iota // ignore first value by assigning to blank identifier         KB ByteSize = 1 << (10 * iota)    MB    GB    TB    PB    EB    ZB    YB)

The ability to attach a method such as String to a type makes it possible for such values to format themselves automatically for printing, even as part of a general type.

Go中可以为大多数类型定义方法 比如为某个类型定义String方法 就可以输出改类型的字符串表达形式

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)}

The expression YB prints as 1.00YB, while ByteSize(1e13) prints as 9.09TB.

通过这个函数 YB可以打印成1.00YB, 而ByteSize(1e13)则打印成9.09TB

Note that it's fine to call Sprintf and friends in the implementation of String methods, but beware of recurring into the String method through the nested Sprintf call using a string format (%s, %q, %v, %x or %X). The ByteSize implementation of String is safe because it calls Sprintf with %f.

在写String函数的时候 可以调用Sprintf以及相关的输出函数 但是要注意防止Sprintf使用格式化修饰符%s, %q, %v, %x, %X, 这里ByteSize的String方法是安全的 因为只用了%f修饰符

Variables 变量初始化

Variables can be initialized just like constants but the initializer can be a general expression computed at run time.

变量可以想常量一样被初始化 但是也可以通过一般的表达式 在运行时再对其初始化

var (    home   = os.Getenv("HOME")    user   = os.Getenv("USER")    goRoot = os.Getenv("GOROOT"))

The init function init初始化函数

Finally, each source file can define its own niladic init function to set up whatever state is required. (Actually each file can have multiple init functions.) And finally means finally: init is called after all the variable declarations in the package have evaluated their initializers, and those are evaluated only after all the imported packages have been initialized.

每个源文件都可以定义自己的init初始化函数(可以有多个init函数)init会在所有包中 变量初始化完成后调用 这个概念可以和其它面向对象的构造函数做对比 最特征化的子类 最后才被初始化 而父类最先被初始化

Besides initializations that cannot be expressed as declarations, a common use of init functions is to verify or repair correctness of the program state before real execution begins.

init的通常用在 程序真正执行前 验证并且修复程序的状态

func init() {    if user == "" {        log.Fatal("$USER not set")    }    if home == "" {        home = "/home/" + user    }    if goRoot == "" {        goRoot = home + "/go"    }    // goRoot may be overridden by --goroot flag on command line.    flag.StringVar(&goRoot, "goroot", goRoot, "Go root directory")}

转载于:https://my.oschina.net/pengfeix/blog/108879

你可能感兴趣的文章
老菜鸟苦战oracle asm
查看>>
C++/CLI:第一流的CLI语言
查看>>
实战:Windows Server 2008 移动活动目录数据库
查看>>
c#程序异常任务管理器弹出一个非程序名
查看>>
[设计模式]工厂方法模式
查看>>
oc52--autorelease1
查看>>
[Android]对BaseAdapter中ViewHolder编写简化
查看>>
Javascript的Error对象在不同浏览器是不一样的.
查看>>
编辑时snapping的添加
查看>>
用 WPF 写的颜色拾取器
查看>>
linux 下office软件推荐
查看>>
NodeJS 初学之安装配置环境
查看>>
【转】使用sklearn优雅地进行数据挖掘
查看>>
win8: 清除iframe的缓存
查看>>
区块链的技术——账本是去中心化的分布式存储,加密+校验(哈希二叉树)+多数选举来防止篡改...
查看>>
从连接触发删除事件
查看>>
Linux 小知识翻译 - 「动态DNS」(DDNS)
查看>>
公积金联名卡——提取公积金用,用身份证即可办理
查看>>
Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)...
查看>>
有效的域名后缀列表
查看>>