头图

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

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

References


coding进阶
116 声望18 粉丝