Почему я могу сделать следующее, чтобы определить итератор в Go:
func f() func() int {
i := 1
return func() int {
i++
return i
}
}
но это приведет к ошибке переменной не используется (i
не используется)?
func f() func() int {
i := 1
return func() (i int) {
i++
return
}
}
основная функция:
func main() {
iter := f()
fmt.Println(iter())
fmt.Println(iter())
fmt.Println(iter())
fmt.Println(iter())
}
Для меня обе версии делают одно и то же: они используют f
в качестве итератора. f
использует замыкания (точнее i
). Первая версия явно возвращает увеличенный i
, а вторая неявно, ссылаясь на него через именованный возвращаемый тип.
Для меня обе версии одинаковы, так почему я получаю сообщение об ошибке?
Во втором случае возвращаемое значение (i int)
скрывает внешнее объявление i := 1
. Итак, это первое i
, которое не используется. Это означает, что второй пример вообще не является замыканием.
С точки зрения обзора ваш второй пример такой же, как:
func f() func() int {
i := 1
return func(i int) int {
i++
return
}
}
В этом случае должно быть ясно, что внутренний i
отчетлив и затеняет внешний.
@User12547645 Эффективный переход: именованные параметры результата
@ User12547645: «Параметры результата действуют как обычные локальные переменные, и функция может присваивать им значения по мере необходимости». Как всегда, прочитайте спецификацию языка программирования Go: golang.org/ref/spec.
Спасибо @icza. Поэтому, если я использую именованный возвращаемый параметр, этот параметр инициализируется как нулевое значение (0 для целых чисел). Вот почему это похоже на новый параметр. Спасибо.
Спасибо большое. Я не знал этого. Не могли бы вы указать, почему именованное возвращаемое значение совпадает с именованным аргументом? У вас есть ссылка, где я мог бы прочитать об этом?