This article has participated in the Denver Nuggets Creators Camp 3 “More Productive writing” track, see details: Digg project | creators Camp 3 ongoing, “write” personal impact.

We know that iota is often used in const expressions, where the value starts at 0 and +1 for each additional line.

Iota can simplify the definition of constants, and the rules will be introduced in a few warm-up exercises to see how well you understand ioTA.

The title

  1. What is the value of each of the following constants?
type Priority int
const (
 LOG_EMERG Priority = iota
 LOG_ALERT
 LOG_CRIT
 LOG_ERR
 LOG_WARNING
 LOG_NOTICE
 LOG_INFO
 LOG_DEBUG
)
Copy the code

The code comes from the log module, and the LOG_EMERG value is 0, incrementing each of the following constants by 1.

  1. What is the value of each of the following constants?
const (
 mutexLocked = 1 << iota // mutex is locked
 mutexWoken
 mutexStarving
 mutexWaiterShift = iota
 starvationThresholdNs = 1e
)
Copy the code

The code is derived from an implementation of the Go Mutex to indicate address offsets for various status bits.

The answer:

mutexLocked == 1; mutexWoken ==2; mutexStarving ==4; mutexWaiterShift ==3; starvationThresholdNs ==1000000
Copy the code
  1. What is the value of each of the following constants?
const (
 bit0, mask0 = 1 << iota.1<<iota - 1
 bit1, mask1
 _, _
 bit3, mask3
)
Copy the code

The answer:

bit0 == 1, mask0 = =0, bit1 = =2, mask1 = =1, bit3 = =8, mask3 = =7
Copy the code

Iota rules

Many information introduction rules are:

  1. Iota is reset to 0 when the const keyword is present;
  2. The ioTA value increases by 1 for each new line in the const declaration block.

Iota represents the row index of a const block (subscript 0).

Another important feature of const declarations is that the first constant must specify an expression, and subsequent constants inherit the expression if they do not have one.

So, let’s look at the code above:

const (
 bit0, mask0 = 1 << iota.1<<iota - 1 //const iota==0 on line 0
 bit1, mask1 Const iota==1, iota==1, iota==1
 _, _ Const iota==2 on line 2
 bit3, mask3 //const iota==3
)
Copy the code

Resolution:

  • Bit0, mask0 = 1<<0, 1<< 0-1, so bit0 == 1, mask0 == 0;
    • 1 << 0 is to shift 1 in base 2 by 0 bits to the left, the result is still 1
  • The first line does not specify that the expression inherits the first line, namely bit1, mask1 = 1<<1, 1<< 1-1, so bit1 == 2, mask1 == 1;
  • Line 2 does not define constants
  • Line 3 does not specify that the expression inherits from the first line, namely bit3, mask3 = 1<<3, 1<< 3-1, so bit0 == 8, mask0 == 7;

The principle of

Each line in the const block is described in Go using the spec data structure, which is declared as follows:

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
}
Copy the code

This section contains the constants defined in a row. If N constants are defined in a row, the length of the ValueSpec.Names section is N.

A const block is actually a slice of type spec that represents multiple lines within a const.

The pseudo-algorithm for constructing constants during compilation is as follows:

for iota, spec := range ValueSpecs {
 for i, name := range spec.Names {
 obj := NewConst(name, iota...).// IoTA is passed in here to construct constants. }}Copy the code

You can see that IOTA is actually an index that traverses a const block and does not increment even if ioTA is used multiple times in each row.