1、 常量可以是全局常量,也可以是函数内部的局部常量。常量的值不可修改,常量表达式的值在编译期计算,而不是在运行期。存储在常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。当常量比较少时,推荐如下:
const 常量名1 = 常量值/常量表达式
const 常量名2 = 常量值/常量表达式
2、和变量声明一样,可以批量声明多个常量,当常量较多时:推荐
const (
常量名1 【类型名称1】= 常量值/常量表达式
常量名2 【类型名称2】= 常量值/常量表达式
常量名3 【类型名称3】= 常量值/常量表达式
)
其中数据类型可以省略,第一个常量必须给定一个确定的值,这里就是常量名1 。一般建议是每个都给定值,且一般也不用写常量类型,除非有必要,也可以给部分常量赋值,第一个必须给定,其余的都可不给,没给定的就取值为上一个显示给定的值,还可以用iota来赋值。第一个常量赋值有:iota赋值/正常赋值。
iota的规则是:iota从0开始自增,从第一个表达式开始为0,依次递增,后面的常量则是使用相同的表达式,只是iota的值不同而已。简单地讲,每遇到一次 const 关键字,iota 就重置为 0,且iota只能用在给常量赋值语句中。iota的值按照每走过一行(该行有常量才算)而自增。
const(
a = iota //a=0
b = iota + 5 //b=6
c //c=7 沿用了 iota + 5这个表达式
d //d=8
)
const(
a, b = iota, iota + 5 //a=0,b=5,这就要求紧接着下面行如果是没有显式赋值,则必须都是两个常量,或者单独赋值。对应赋值
c, d //c=1,d=6
e, f //e=2,f=7
g = iota //g=0
)
第一个声明了常量类型,然后用iota初始化常量。
const (
a = iota
b = iota
c = iota
)
const (
Sunday = 1 << (iota + 1)
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
type Color int
const (
RED Color = iota // 0
ORANGE // 1
YELLOW // 2
GREEN // ..
BLUE
INDIGO
VIOLET // 6
)
3、常量表达式:常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex和unsafe.Sizeof(§13.1)。
4、无类型常量,只有常量可以是无类型的。。虽然一个常量可以有任意有一个确定的基础类型,例如int或float64,或者是类似time.Duration这样命名的基础类型,但是许多常量并没有一个明确的基础类型。
编译器为这些没有明确的基础类型的数字常量提供比基础类型更高精度的算术运算;你可以认为至少有256bit的运算精度。
这里有六种未明确类型的常量类型,分别是:
无类型的布尔型: true,false
无类型的整数:
无类型的字符:
无类型的浮点数:
无类型的复数:
无类型的字符串:字符串面值常量是无类型的字符串类型
当一个无类型的常量被赋值给一个变量的时候,就像下面的第一行语句,或者出现在有明确类型的变量声明的右边,如下面的其余三行语句,无类型的常量将会被隐式转换为对应的类型,如果转换合法的话。
var f float64 = 3 + 0i // untyped complex -> float64
f = 2 // untyped integer -> float64
f = 1e123 // untyped floating-point -> float64
f = 'a' // untyped rune -> float64
上面的语句相当于:
var f float64 = float64(3 + 0i)
f = float64(2)
f = float64(1e123)
f = float64('a')
无论是隐式或显式转换,将一种类型转换为另一种类型都要求目标可以表示原始值。对于浮点数和复数,可能会有舍入处理:
const (
deadbeef = 0xdeadbeef // untyped int with value 3735928559
a = uint32(deadbeef) // uint32 with value 3735928559
b = float32(deadbeef) // float32 with value 3735928576 (rounded up)
c = float64(deadbeef) // float64 with value 3735928559 (exact)
d = int32(deadbeef) // compile error: constant overflows int32
e = float64(1e309) // compile error: constant overflows float64
f = uint(-1) // compile error: constant underflows uint
)
对于一个没有显式类型的变量声明(包括简短变量声明),常量的形式将隐式决定变量的默认类型,就像下面的例子:
i := 0 // untyped integer; implicit int(0)
r := '\000' // untyped rune; implicit rune('\000')
f := 0.0 // untyped floating-point; implicit float64(0.0)
c := 0i // untyped complex; implicit complex128(0i)
注意有一点不同:无类型整数常量转换为int,它的内存大小是不确定的,但是无类型浮点数和复数常量则转换为内存大小明确的float64和complex128。 如果不知道整型类型的内存大小是很难写出正确的数值算法的,因此Go语言不存在整型类似的不确定内存大小的浮点数和复数类型。
如果要给变量一个不同的类型,我们必须显式地将无类型的常量转化为所需的类型,或给声明的变量指定明确的类型,像下面例子这样:
var i = int8(0)
var i int8 = 0
当尝试将这些无类型的常量转为一个接口值时(见第7章),这些默认类型将显得尤为重要,因为要靠它们明确接口对应的动态类型。
fmt.Printf("%T\n", 0) // "int"
fmt.Printf("%T\n", 0.0) // "float64"
fmt.Printf("%T\n", 0i) // "complex128"
fmt.Printf("%T\n", '\000') // "int32" (rune)