Go の "defer" の複雑さを理解する
Go の Defer は、関数の実行を延期できる強力なキーワードです。囲んでいる関数が返されるまで呼び出します。ただし、defer を使用する場合、関数パラメータと戻り値の評価順序を把握することが重要です。
評価順序と遅延
Defer_statements のドキュメントによると、 「defer」ステートメントが実行されるたびに、「呼び出しに対する関数の値とパラメーターは通常どおり評価され、新たに保存されますが、実際の関数は呼び出されません。」これは、遅延関数を呼び出すと、最初に関数パラメーターが評価され、その後、関数の戻り時に実際の関数が呼び出されることを意味します。
シナリオ
詳しく見てみましょうユーザーの年齢に基づいてチケット価格を正しく計算するのに問題があるという特定の例を見てみましょう。コードでは、引数 ticketPrice を使用して printTicket への遅延呼び出しを定義します。指定された年齢に応じて ticketPrice が設定され、適切なチケット価格が返されることを期待しています。
問題
合格しようとしているために問題が発生します。 printTicket への初期化されていない「ticketPrice」。 main の戻り中に printTicket への遅延呼び出しが実行されると、初期化されていない「ticketPrice」はデフォルトのゼロ値になり、9.99 の価格のみが出力されます。
Solution
これを解決するには、printTicket の呼び出しを延期する前に、「ticketPrice」を正しい値に初期化する必要があります。あるいは、変更された関数呼び出し構文を使用して、参照によって "ticketPrice" を渡すことができ、遅延呼び出しが更新された値を確実に取得できるようにすることもできます。
Example
以下は、defer の正しい使用法を示すコードの変更バージョンです。
<code class="go">package main import "fmt" func printTicket(age int) float64 { fmt.Println("...order is 2...") switch { case age <= 13: return 9.99 case age > 13 && age < 65: return 19.99 default: return 12.99 } } func main() { var age int defer fmt.Println("...order is 4...Your age is:", getAge(&age)) // Modify the calling syntax here: var ticketPrice = 0.0 defer fmt.Println("...order is 3...Your ticket price is:", printTicket(age, &ticketPrice)) } func getAge(age *int) int { fmt.Println("...order is 1...") fmt.Print("Enter age=") fmt.Scanln(age) return *age }</code>
これらの変更により、「printTicket」呼び出しの前に「ticketPrice」変数が適切に初期化され、正しいチケット価格が保証されます。計算されて出力されます。
以上がGo では defer は関数パラメーターでどのように機能しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。