### iota
`iota`是`go`语言的常量计数器,只能在常量的表达式中使用
使用规则:
* iota代表了const声明块的行索引(下标从0开始)
源码:
const块中每一行在GO中使用spec数据结构描述,spec声明如下:
~~~GO
// A ValueSpec node represents a constant or variable declaration
// (ConstSpec or VarSpec production).
//
ValueSpec struct {
Doc *CommentGroup // associated documentation; or nil
Names []*Ident // value names (len(Names) > 0)
Type Expr // value type; or nil
Values []Expr // initial values; or nil
Comment *CommentGroup // line comments; or nil
}
~~~
这里我们只关注ValueSpec.Names, 这个切片中保存了一行中定义的常量,如果一行定义N个常量,那么ValueSpec.Names切片长度即为N。
const块实际上是spec类型的切片,用于表示const中的多行。
所以编译期间构造常量时的伪算法如下:
~~~GO
for iota, spec := range ValueSpecs {
for i, name := range spec.Names {
obj := NewConst(name, iota...) //此处将iota传入,用于构造常量
...
}
}
~~~
从上面可以更清晰的看出iota实际上是遍历const块的索引,每行中即便多次使用iota,其值也不会递增
#### 示例一
使用_跳过某些值
~~~
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
)
~~~
#### 示例二
~~~go
const (
mutexLocked = 1 << iota // mutex is locked
mutexWoken
mutexStarving
mutexWaiterShift = iota
starvationThresholdNs = 1e6
)
~~~
题目解释:
以上代码取自Go互斥锁Mutex的实现,用于指示各种状态位的地址偏移。
参考答案:
mutexLocked == 1;mutexWoken == 2;mutexStarving == 4;mutexWaiterShift == 3;starvationThresholdNs == 1000000
#### 示例三
~~~go
const (
bit0, mask0 = 1 << iota, 1<<iota - 1
bit1, mask1
_, _
bit3, mask3
)
~~~
参考答案:
bit0 == 1, mask0 == 0, bit1 == 2, mask1 == 1, bit3 == 8, mask3 == 7
- 概述
- go语言基础特性
- Go语言声明
- Go项目构建及编译
- go command
- 程序设计原则
- Go基础
- 变量
- 常量
- iota
- 基本类型
- byte和rune类型
- 类型定义和类型别名
- 数组
- string
- 高效字符串连接
- string底层原理
- 运算符
- new
- make
- 指针
- 下划线 & import
- 语法糖
- 简短变量申明
- 流程控制
- ifelse
- switch
- select
- select实现原理
- select常见案例
- for
- range
- range实现原理
- 常见案例
- range陷阱
- Goto&Break&Continue
- Go函数
- 函数
- 可变参数函数
- 高阶函数
- init函数和main函数
- 匿名函数
- 闭包
- 常用内置函数
- defer
- defer常见案例
- defer规则
- defer与函数返回值
- defer实现原理
- defer陷阱
- 数据结构
- slice
- slice内存布局
- slice&array
- slice底层实现
- slice陷阱
- map
- Map实现原理
- 集合
- List
- Set
- 线程安全数据结构
- sync.Map
- Concurrent Map
- 面向对象编程
- struct
- 匿名结构体&匿名字段
- 嵌套结构体
- 结构体的“继承”
- struct tag
- 行为方法
- 方法与函数
- type Method Value & Method Expressions
- interface
- 类型断言
- 多态
- 错误机制
- error
- 自定义错误
- panic&recover
- reflect
- reflect包
- 应用示例
- DeepEqual
- 反射-fillObjectField
- 反射-copyObject
- IO
- 读取文件
- 写文件
- bufio
- ioutil
- Go网络编程
- tcp
- tcp粘包
- udp
- HTTP
- http服务
- httprouter
- webSocket
- go并发编程
- Goroutine
- thread vs goroutine
- Goroutine任务取消
- 通过channel广播实现
- Context
- Goroutine调度机制
- goroutine调度器1.0
- GMP模型调度器
- 调度器窃取策略
- 调度器的生命周期
- 调度过程全解析
- channel
- 无缓冲的通道
- 缓冲信道
- 单向信道
- chan实现原理
- 共享内存并发机制
- mutex互斥锁
- mutex
- mutex原理
- mutex模式
- RWLock
- 使用信道处理竞态条件
- WaitGroup
- 工作池
- 并发任务
- once运行一次
- 仅需任意任务完成
- 所有任务完成
- 对象池
- 定时器Timer
- Timer
- Timer实现原理
- 周期性定时器Ticker
- Ticker对外接口
- ticker使用场景
- ticker实现原理
- ticker使用陷阱
- 包和依赖管理
- package
- 依赖管理
- 测试
- 单元测试
- 表格测试法
- Banchmark
- BDD
- 常用架构模式
- Pipe-filter pattern
- Micro Kernel
- JSON
- json-内置解析器
- easyjson
- 性能分析
- gc
- 工具类
- fmt
- Time
- builtin
- unsafe
- sync.pool
- atomic
- flag
- runtime
- strconv
- template