package main import ( "fmt" "math" "time" ) //type IP byte // 常量表达式的值在编译期计算,而不是在运行期。 // 每种常量的潜在类型都是基础类型:boolean、string或数字。 func main() { const ( PI = 3.14 e = 2.72 ) fmt.Println(math.Pi) fmt.Println(math.E) fmt.Println(PI) fmt.Println(e) // 所有常量的运算都可以在编译期完成,这样可以减少运行时的工作, // 也方便其他编译优化。当操作数是常量时, // 一些运行时的错误也可以在编译时被发现, // 例如整数除零、字符串索引越界、任何导致无效浮点数的操作等。 // 常量间的所有算术运算、逻辑运算和比较运算的结果也是常量, // 对常量的类型转换操作或以下函数调用都是返回常量结果: // len、cap、real、imag、complex和unsafe.Sizeof(§13.1)。 // 因为它们的值是在编译期就确定的,因此常量可以是构成类型的一部分, // 例如用于指定数组类型的长度: //const IPv4Len = 4 // parseIPv4 parses an IPv4 address (d.d.d.d). //parseIPv4 := func(s string) IP { // var p [IPv4Len]byte // // ... // return p //} // 一个常量的声明也可以包含一个类型和一个值,但是如果没有显式指明类型, // 那么将从右边的表达式推断类型。在下面的代码中, // time.Duration是一个命名类型,底层类型是int64,time.Minute是对应类型的常量。 // 下面声明的两个常量都是time.Duration类型,可以通过%T参数打印类型信息: const noDelay time.Duration = 0 const timeout = 5 * time.Minute fmt.Printf("%T %[1]v\n", noDelay) // "time.Duration 0" fmt.Printf("%T %[1]v\n", timeout) // "time.Duration 5m0s" fmt.Printf("%T %[1]v\n", time.Minute) // "time.Duration 1m0s" // 如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略, // 如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的。例如: const ( a = 1 b c = 2 d ) fmt.Println(a, b, c, d) // "1 1 2 2" // 下面是来自time包的例子,它首先定义了一个Weekday命名类型, // 然后为一周的每天定义了一个常量,从周日0开始。在其它编程语言中, // 这种类型一般被称为枚举类型。 type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturday ) fmt.Printf("%T %[1]v \n", Sunday) // 下面是一个更复杂的例子,每个常量都是1024的幂: const ( _ = 1 << (10 * iota) KiB // 1024 MiB // 1048576 GiB // 1073741824 TiB // 1099511627776 (exceeds 1 << 32) PiB // 1125899906842624 EiB // 1152921504606846976 ZiB // 1180591620717411303424 (exceeds 1 << 64) YiB // 1208925819614629174706176 ) fmt.Println(KiB) }