2016-08-31 4 views
1

Я не понимаю, почему следующие программы печатают 0 1 2. Я думал, что он напечатает 2 2 2.Выполняет ли новый цикл for for цикл последнего цикла цикла?

package main 

import (
    "fmt" 
) 

func main() { 
    var funcs []func() 
    for i := 0; i < 3; i++ { 
     idx := i 
     funcs = append(funcs, func() { fmt.Println(idx) }) 
    } 

    for _, f := range funcs { 
     f() 
    } 
} 

Мои рассуждения о нем следует печатать 2 2 2, что каждый прогон для цикла общий одинаковый объем (например., Второй прогон для цикла не прекращает объем 1-го запуска, объем являются общими). Таким образом, ссылка idx разделяется анонимной функцией, созданной в каждом цикле for. Таким образом, когда цикл заканчивается, все 3 созданные функции имеют одинаковую ссылку idx, значение которой равно 2.

Поэтому я думаю, что вопрос сводится к следующему: выполняет ли новый цикл (например, i == 2) для цикла завершает область действия последнего цикла (например, i == 1) для цикла? Был бы признателен, если бы ответ указал мне на golang spec. (Я не мог найти спецификацию, упоминающую об этом).

ответ

2

Из спецификации https://golang.org/ref/spec#For_statements

А "за" заявление определяет повторное выполнение блока.

Каждый из этих блоков имеет свой собственный объем и не является вложенным или общим. Но

Каждый оператор «если», «для» и «переключатель» считается в своем неявном блоке .

так переменная я в вашем фрагменте кода является общим и

for i := 0; i < 3; i++ { 
     funcs = append(funcs, func() { fmt.Println(i) }) 
} 

for _, f := range funcs { 
     f() 
} 

напечатает 3 3 3, как и ожидалось.

+0

Спасибо, это объясняет мой вопрос. Неявный блок «each» if »,« for »и« switch »statement является родительским блоком для блока исполнения, правильно? –

Смежные вопросы