Before Go1.22

This range loop:

for i, v := range exp {...}

after compilation is semantically equivalent to:

var i Type
var v Type
 
expT := exp
lenT := len(exp)
for iT := 0; iT < lenT; iT++ {
	i = iT
	vT := expT[iT]
	v = vT
	// original body
}

From this, we can note a couple of important details:

  • The range loop expression exp is evaluated only once and is assigned to a temporary variable (a copy of the original)
  • The variable v is a single variable that takes different values in each loop iteration
  • The variable v is a copy of the loop element’s value
  • The variable i is a single variable that takes different values in each loop iteration
  • The variable i is a copy of the loop index’s value

After Go1.22 (Loopvar Experiment)

This 3-clause for loop:

for i := 0; i < N; i++ {...}

after compilation is semantically equivalent to:

iT := 0
first := true
for {
	i := iT
	if first {
		first = false
	} else {
		i++
	}
	if !(i < N) {
		break
	}
	// original body
	iT = i
}

This range loop:

for i, v := range exp {...}

after compilation is semantically equivalent to:

var iT Type
var vT Type
 
for iT, vT = range exp {
	i := iT
	v := vT
	// original body
}

From this, we can note a couple of important details:

  • The range loop expression exp is evaluated only once and is assigned to a temporary variable (a copy of the original)
  • The variable v is a newly declared variable at each iteration
  • The variable v is a copy of the loop element’s value
  • The variable i is a newly declared variable at each iteration
  • The variable i is a copy of the loop index’s value

References