go——常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量
常量中的数据类型只可以是布尔值、数字型(整数型、浮点型和复数)和字符串。
常量的定义格式:
const identifier [type] = value
你可以省略类型说明符[type],因为编译器可以根据变量的值来推断其类型。
显式定义:
const b string = “abc”
隐式定义:
const b = “abc”
多个相同类型的声明可以简写为:
const c_name1,c_name2 = value1,value2
下面是一个综合示例:
package main
const x int = 100 //显式定义
const y = false //隐式定义
const m, n = 111, 222 //一次定义多个,前提条件是类型一致
func main() {
const ( //以组的方式批量定义
i, f = 0, 1
b = false
)
}
需要说明的是定义常量但是不使用常量并不会报错。
如果显式定义常量,必须保证常量左右两边的类型必须一致,需要的时候可以做显式转化。
同时,右值不能超出常量类型取值范围,否则会引发溢出错误。
const k uint8 = 999 //constant 999 overflows uint8,uint8的最大取值是255
常量也可以是某些编译器能计算出结果的表达式。
const ( ptrSize = unsafe.Sizeof(uintptr(0)) strSize = len("hello, world") )
在常量组中如不指定类型和初始化值,则与上一行非空常量右值相同。
package main import "fmt" func main() { const ( x int = 18 y //与上一行x类型和值相同 z = "abc" s ) fmt.Printf("%T, %v\n", y, y) fmt.Printf("%T, %v\n", s, s) } /* 结果: int, 18 string, abc */
iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota在const关键字出现时将被重置为0(const内部的第一行之前),
const中每新增一行常量声明将使iota计数一次(iota可以理解为const语句块中的行索引。)
const ( a = iota b = iota c = iota )
第一个iota等于0,每当iota在新的一行被使用时,它的值都会自动加1,所以a=0,b=1,c=2,
可以简写为如下形式:
const ( a = iota b c )
看几个简单的例子:
示例1:
package main import "fmt" const ( _ = iota kb = 1 << (10 * iota) mb gb ) /* gb和mb的值与kb的值相同 (kb = 1) << (10 * 1) 1 * 2**10 = 1024 (mb = 1) << (10 * 2) 1 * 2**20 = 1048576 (gb = 1) << (10 * 3) 1 * 2**30 = 1073741824 */ //iota值是自增的,向左移动n位,就是乘以2的n次方 func main() { fmt.Println(kb, mb, gb) } /* 结果: 1024 1048576 1073741824 */
示例2:
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "hello" //重新赋值,但是iota +=1 e //引用上面,但是iota +=1 f = 100 //重新赋值 g h = iota //7 如果中断iota自增,必须显式恢复 i //8 ) fmt.Println(a, b, c, d, e, f, g, h, i) } //a, b, c, d, e, f, g, h, i //0 1 2 hello hello 100 100 7 8
常量与变量本质的差别
不同于变量在运行期间分配存储内存,常量通常会被编译器在预处理阶段直接展开,作为指令数据使用
package main import "fmt" var x = 0x100 const y = 0x200 func main() { fmt.Println(&x, x) fmt.Println(&y, y) //cannot take the address of y 无法获取内存地址 }
数字常量不会被分配存储空间,无需像变量那样通过内存来取值,因此无法获取内存地址。