関数の戻りパラメータに名前を付けると、どのような利点がありますか?
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 には、名前付きの結果パラメーターに関するセクションがあります。
Go 関数の戻り値または結果の「パラメーター」には、入力パラメーターと同様に、名前を付けて通常の変数として使用できます。名前が付けられると、関数の開始時にその型のゼロ値に初期化されます。関数が引数なしで return ステートメントを実行する場合、結果パラメーターの現在の値が戻り値として使用されます。
名前は必須ではありませんが、コードを短く明確にすることができます。名前はドキュメントです。nextInt の結果に名前を付けると、返された int がどれであるかが明らかになります。
func nextInt(b []byte, pos int) (value, nextPos int) {
[...]
名前付き戻り変数のもう 1 つの特別な用途は、遅延関数リテラルによってキャプチャされることです。些細な例:
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 の戻り値を変更する機会があることです。
少なくとも 2 つの場合に役立ちます。
返す変数を宣言する必要があるときはいつでも。例えば
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
}
等。