Какие преимущества возникают при названии параметра (-ов) возврата функции?
func namedReturn(i int) (ret int) {
ret = i
i += 2
return
}
func anonReturn(i int) int {
ret := i
i += 2
return ret
}
Какие преимущества возникают при названии параметра (-ов) возврата функции?
func namedReturn(i int) (ret int) {
ret = i
i += 2
return
}
func anonReturn(i int) int {
ret := i
i += 2
return ret
}
Есть несколько преимуществ для их обозначения:
Есть и недостатки, в основном, что их легко случайно замаскировать, объявив переменную с тем же именем.
Эффективный Go имеет раздел по названным параметрам результата.
Другое специальное использование для именованной возвращаемой переменной должно быть записано литералом отложенной функции. Тривиальная иллюстрация:
package main
import (
"errors"
"fmt"
)
func main() {
fmt.Println(f())
}
var harmlessError = errors.New("you should worry!")
func f() (err error) {
defer func() {
if err == harmlessError {
err = nil
}
}()
return harmlessError
}
Вывод <nil>
. В более практичных сценариях отложенная функция может обрабатывать паники и может изменять другие возвращаемые значения, помимо результата ошибки. Магия в общем случае заключается в том, что отложенный литерал имеет шанс изменить возвращаемые значения f после того, как f завершается, как обычно, так и паникой.
Он полезен, по крайней мере, в двух случаях:
Всякий раз, когда вам приходится объявлять переменные, которые вы собираетесь вернуть. Например.
func someFunc() (int, error) {
var r int
var e error
ok := someOtherFunc(&r) // contrived, I admit
if !ok {
return r, someError()
}
return r, nil
}
против.
func someFunc() (r int, e error) {
ok := someOtherFunc(&r)
if !ok {
e = someError()
}
return
}
Это становится более важным, так как количество путей выполнения через функцию увеличивается.
Когда вы документируете возвращаемые значения и хотите ссылаться на них по имени. godoc
рассматривает часть возвращаемых переменных в сигнатуре функции.
Например, имена возвращаемых параметров доступны, ну, имя.
func foo() (a, b, c T) {
// ...
if qux {
b = bar()
}
// ...
return
}
Это непросто реплицировать без имен возвращаемых параметров. Нужно было бы ввести локальные переменные по существу той же функциональности, что и имена возвращаемых параметров:
func foo() (T, T, T) {
var a, b, c T
// ...
if qux {
b = bar()
}
// ...
return a, b, c
}
Так что проще разрешить это напрямую.
Кроме того, они доступны также в другом направлении:
func foo() (a, b, c T) {
// ...
if a > c {
b = bar()
}
// ...
return
}
Etc.