Iota
iota
is the pre-declared identifier of Go language, used for constant declaration.
The value of ---8a99ee7d2a042cb63fc68b41956c9ca1 iota
is const
the row index in the statement block. The value starts from 0 and increases by 1 each time. Through the following code example, let's review the characteristics of iota
.
const (
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota == 0)
b = 1 << iota // b == 2 (iota == 1)
c = 3 // c == 3 (iota == 2, unused)
d = 1 << iota // d == 8 (iota == 3)
)
const (
u = iota * 42 // u == 0 (untyped integer constant)
v float64 = iota * 42 // v == 42.0 (float64 constant)
w = iota * 42 // w == 84 (untyped integer constant)
)
const x = iota // x == 0
const y = iota // y == 0
const (
class1 = 0
class2 // class2 = 0
class3 = iota //iota is 2, so class3 = 2
class4 // class4 = 3
class5 = "abc"
class6 // class6 = "abc"
class7 = iota // class7 is 6
)
Bug
On March 15, 2022, the Go official team officially released Go version 1.18. Go 1.18 is the version with the biggest changes since the birth of the Go language, introducing many new features and performance optimizations such as generics, fuzzing, and workspace mode.
There is no bug-free system in the world, and Go is certainly no exception. Go 1.18 introduced a bug related to iota
.
Let's take a look at the following program and think about what the output should be?
package main
import "fmt"
const C1 = iota
const C2 = iota
func test1() {
fmt.Println("C1=", C1, " C2=", C2)
}
func main() {
test1()
}
Think for a few seconds. . .
Before Go 1.18, the result printed by the above program was
C1= 0 C2= 0
As of Go 1.18, the result printed by the above program is
C1= 0 C2= 1
Obviously, this is a bug, because const C1 = iota
and const C2 = iota
are independent of each other const
statement block, so these 2 const
The values in iota
are all 0.
The Go official also claimed this bug . Robert Griesemer, the main designer of the Go language, explained the reason for the bug:
No need to bisect. This is due to a completely new type checker, so it won't be useful to pin-point to a single change. I've identified the bug and will have a fix in a little bit.
This is clearly a bad bug; but only manifests itself when using iota outside a grouped constant declaration, twice.
As a temporary work-around, you can change your code to:
// OpOr is a logical or (precedence 0) const (OpOr Op = 0 + iota<<8) // OpAnd is a logical and (precedence 1) const (OpAnd Op = 1 + iota<<8)
(put parentheses around the const declarations).
This bug is caused by the introduction of a brand new type checker in Go.
This bug only occurs in global , ungrouped constant declarations and is expected to be fixed in Go 1.19.
We use parentheses ()
to wrap the declaration, that is, use grouped constant declarations, so there will be no such bug.
package main
import "fmt"
const (
C1 = iota
)
const (
C2 = iota
)
func test1() {
fmt.Println("C1=", C1, " C2=", C2)
}
func main() {
test1()
}
The result of executing the above program is:
C1= 0 C2= 0
Also, there is no such bug for local constant declarations.
package main
import "fmt"
func test1() {
const C1 = iota
const C2 = iota
fmt.Println("C1=", C1, " C2=", C2)
}
func main() {
test1()
}
The result of executing the above program is:
C1= 0 C2= 0
Recommended reading
Generics
Fuzzing
Workspace Mode
open source address
Articles and sample code are open sourced on GitHub: Beginner, Intermediate, and Advanced Tutorials in Go .
Official account: coding advanced. Follow the official account to get the latest Go interview questions and technology stacks.
Personal website: Jincheng's Blog .
Zhihu: Wuji
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。