## 5.9\. 初始化
尽管表面看来和 C 或 C++ 的初始化没什么不同,Go 的更够强。复杂结构可在初始化时架设,并且不同包的物件的初始化顺序问题也得到正确处理。
### 5.9.1\. Constants 常量初始化
常量在 Go 里是 —— 不变的。它们在编译时生成,即便是局部定义在函数里。它只能是数,字串或布尔。因为编译态的限制,定义它们的表达式必须是常量表达式,可以被编译器求值。例如,1<<3 是常量表达式, math.Sin(math.Pi/4) 不是,因为 math.Sin 的函数调用发生在运行态。
Go 的列举常量可用 iota 生成。 因为 iota 可以是表达式的一部分,并且表达式可以隐含重复,打造一套精致的值可以变得很容易。
```
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 等方法的本领,使值自动排版打印自己变得可能,即使只作为通用类型的一部分。
```
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
### 5.9.2\. 变量初始化
变量和常量的初始化一样,但可以用运行态计算的普通表达式。
```
var (
HOME = os.Getenv("HOME")
USER = os.Getenv("USER")
GOROOT = os.Getenv("GOROOT")
)
```
### 5.9.3\. init函数
最后,每个源文件可以定义自身的 init() 函数来安排所需的状态。唯一的限制是,尽管够程可在初始化时启动,它们只在初始完成后执行;初始化永远是单一的执行序列。最后之后,init() 发生在包里所有变量初始化之后,而其又发生在所有的包全部导入之后。
除了初始化不能表示为声明外,init() 函数常用来在程序运行前验证或修补其状态。
```
func init() {
if USER == "" {
log.Exit("$USER not set")
}
if HOME == "" {
HOME = "/usr/" + USER
}
if GOROOT == "" {
GOROOT = HOME + "/go"
}
// GOROOT may be overridden by --goroot flag on command line.
flag.StringVar(&GOROOT, "goroot", GOROOT, "Go root directory")
}
```
- 1. 关于本文
- 2. Go语言简介
- 3. 安装go环境
- 3.1. 简介
- 3.2. 安装C语言工具
- 3.3. 安装Mercurial
- 3.4. 获取代码
- 3.5. 安装Go
- 3.6. 编写程序
- 3.7. 进一步学习
- 3.8. 更新go到新版本
- 3.9. 社区资源
- 3.10. 环境变量
- 4. Go语言入门
- 4.1. 简介
- 4.2. Hello,世界
- 4.3. 分号(Semicolons)
- 4.4. 编译
- 4.5. Echo
- 4.6. 类型简介
- 4.7. 申请内存
- 4.8. 常量
- 4.9. I/O包
- 4.10. Rotting cats
- 4.11. Sorting
- 4.12. 打印输出
- 4.13. 生成素数
- 4.14. Multiplexing
- 5. Effective Go
- 5.1. 简介
- 5.2. 格式化
- 5.3. 注释
- 5.4. 命名
- 5.5. 分号
- 5.6. 控制流
- 5.7. 函数
- 5.8. 数据
- 5.9. 初始化
- 5.10. 方法
- 5.11. 接口和其他类型
- 5.12. 内置
- 5.13. 并发
- 5.14. 错误处理
- 5.15. Web服务器
- 6. 如何编写Go程序
- 6.1. 简介
- 6.2. 社区资源
- 6.3. 新建一个包
- 6.4. 测试
- 6.5. 一个带测试的演示包
- 7. Codelab: 编写Web程序
- 7.1. 简介
- 7.2. 开始
- 7.3. 数据结构
- 7.4. 使用http包
- 7.5. 基于http提供wiki页面
- 7.6. 编辑页面
- 7.7. template包
- 7.8. 处理不存在的页面
- 7.9. 储存页面
- 7.10. 错误处理
- 7.11. 模板缓存
- 7.12. 验证
- 7.13. 函数文本和闭包
- 7.14. 试试!
- 7.15. 其他任务
- 8. 针对C++程序员指南
- 8.1. 概念差异
- 8.2. 语法
- 8.3. 常量
- 8.4. Slices(切片)
- 8.5. 构造值对象
- 8.6. Interfaces(接口)
- 8.7. Goroutines
- 8.8. Channels(管道)
- 9. 内存模型
- 9.1. 简介
- 9.2. Happens Before
- 9.3. 同步(Synchronization)
- 9.4. 错误的同步方式
- 10. 附录
- 10.1. 命令行工具
- 10.2. 视频和讲座
- 10.3. Release History
- 10.4. Go Roadmap
- 10.5. 相关资源