🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 5.9\. 初始化 尽管表面看来和 C 或 C++ 的初始化没什么不同,Go 的更够强。复杂结构可在初始化时架设,并且不同包的物件的初始化顺序问题也得到正确处理。 ### 5.9.1\. Constants 常量初始化 常量在 Go 里是 —— 不变的。它们在编译时生成,即便是局部定义在函数里。它只能是数,字串或布尔。因为编译态的限制,定义它们的表达式必须是常量表达式,可以被编译器求值。例如,1&lt;&lt;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") } ```