2015-10-19 8 views
2

Это функция в Голанге, которая использует defer для изменения именованного возвращаемого значения функции c().Постоянна, возвращаемая функцией, автоматически становится значением именованной возвращаемой переменной

package main 

import "fmt" 

func c() (i int) { 
    defer func() { }()  
    defer fmt.Println("our i is", i) 
    return 45 
    } 

func main() { 
    fmt.Println(c()) 
} 

Выход программы:

наш я есть 0

изменения анонимного FUNC() в коде

func c() (i int) { 
     defer func() { i = 1 }() 
     defer fmt.Println("our i is", i) 
     return 45 
     } 

    func main() { 
     fmt.Println(c()) 
    } 

Это приводит к выходу:

наш я есть 0

Похоже, что возвращаемое значение 45 копируется я не автоматически, если другое значение кладется внутри я. Но я не уверен на 100%, если это точная причина выхода

ответ

2

В отложенных функциях у вас есть возможность изменять значения параметров результата.

Когда вызывается отсроченные функции, значения, указанные в инструкции return, уже установлены.

Если есть несколько отложенных функций, они выполняются в порядке LIFO (последний раз, первый раз).

В вашем втором примере выполняется fmt.Println(), а затем другая анонимная функция.

Но что вам нужно знать, что при выполнении инструкции defer аргументы отложенной функции оцениваются немедленно, а не когда функция отсрочки будет выполняться (позже, перед возвратом).

Spec: Defer statements:

Каждый раз, «отложить» выполняется оператор, значение функции и параметры вызова являются evaluated as usual и сохранены заново, но фактическая функция не вызывается. Вместо этого отложенные функции вызывают непосредственно перед возвратом окружающей функции, в обратном порядке они откладываются.

Так эта линия:

defer fmt.Println("our i is", i) 

всегда будет означать называть fmt.Println() с i = 0 аргументом:

fmt.Println("our i is", 0) 

Потому что, когда работает эта линия, i имеет значение 0.

Так что в вашем примере 2 fmt.Println() печатает 0, затем запускает другую функцию отложенной, которая устанавливает i к 1 и это то, что возвращается.

Вашего первый пример просто печатает что-то (i = 0), но отложенные функции в первом примере не изменить значение i так 45 будет возвращена (и напечатанная функцией fmt.Println() от main()).

Пожалуйста, смотрите следующие вопросы/ответы больше по теме:

Defer usage clarification

How to return a value in a Go function that panics?

+0

реверсивный порядок отчетности Defer также дает точно такой же вывод. Другое дело, почему именно постоянная 45 выдается в первый раз, но не во втором случае? –

+0

@AdityaSanghi '45' выводится оператором' fmt.Println() 'в функции **' main() '**, а не' Println() 'в функции' c() '. '45' возвращается из' c() ', вот почему. – icza

+0

Но почему он возвращает 1, когда я явно изменяю i (во втором примере кода). В принципе, я не понимаю, почему возвращаемые значения ведут себя по-разному в двух примерах кода. –

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