# 「golang」理解常量 Constants && iota

## 「golang」理解常量 Constants && iota

``````const pi = 3.1415
const e = 2.7182``````

``````const (
pi = 3.1415
e = 2.7182
)``````

const同时声明多个常量时，如果省略了值则表示和上面一行的值相同。 例如：

``````const (
n1 = 100
n2
n3
)``````

## iota

iota是go语言的常量计数器，只能在常量的表达式中使用。

iota在const关键字出现时将被重置为0。

const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。

``````const (
n1 = iota //0
n2        //1
n3        //2
n4        //3
)``````

### 使用_跳过某些值

``````const (
n1 = iota //0
n2        //1
_
n4        //3
)``````

### iota声明中间插队

``````const (
n1 = iota //0
n2 = 100  //100
n3 = iota //2
n4        //3
)
const n5 = iota //0``````

### 定义数量级

（这里的<<表示左移操作，1<<10表示将1的二进制表示向左移10位，也就是由1变成了10000000000，也就是十进制的1024。同理2<<2表示将2的二进制表示向左移2位，也就是由10变成了1000，也就是十进制的8。）

``````const (
_  = iota
KB = 1 << (10 * iota)
MB = 1 << (10 * iota)
GB = 1 << (10 * iota)
TB = 1 << (10 * iota)
PB = 1 << (10 * iota)
)``````

### 多个iota定义在一行

``````const (
a, b = iota + 1, iota + 2 //1,2
c, d                      //2,3
e, f                      //3,4
)``````

## Constants 常量 官方文档

Constants in Go are just that—constant. They are created at compile time, even when defined as locals in functions, and can only be numbers, characters (runes), strings or booleans. Because of the compile-time restriction, the expressions that define them must be constant expressions, evaluatable by the compiler. For instance, 1<<3 is a constant expression, while math.Sin(math.Pi/4) is not because the function call to math.Sin needs to happen at run time.

In Go, enumerated constants are created using the iota enumerator. Since iota can be part of an expression and expressions can be implicitly repeated, it is easy to build intricate sets of values.

``````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
)``````

The ability to attach a method such as String to any user-defined type makes it possible for arbitrary values to format themselves automatically for printing. Although you'll see it most often applied to structs, this technique is also useful for scalar types such as floating-point types like ByteSize.

``````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)
}``````
The expression YB prints as 1.00YB, while ByteSize(1e13) prints as 9.09TB.

The use here of Sprintf to implement ByteSize's String method is safe (avoids recurring indefinitely) not because of a conversion but because it calls Sprintf with %f, which is not a string format: Sprintf will only call the String method when it wants a string, and %f wants a floating-point value.

7k 声望
915 粉丝
0 条评论