Go では、「defer」ステートメントを使用して、周囲の関数が戻る直前に関数が実行されるようにスケジュールできます。ただし、これは、囲んでいる関数内で変更される変数を扱うときに混乱を招く可能性があります。
次の関数を考えてみましょう:
func printNumbers() { var x int defer fmt.Println(x) for i := 0; i < 5; i++ { x++ } }
Go 仕様では、「defer」ステートメントが実行されると、関数の値とパラメーターが評価され、後の実行のために保存されます。これは、関数が最終的に呼び出されるとき、延期時に評価されたため、x の値は 0 のままであることを意味します。
この問題を解決するには、次のようにします。 「defer」ステートメント内で匿名関数を使用できます:
defer func() { fmt.Println(x) }()
ここで、x は匿名関数のパラメータではないため、 「defer」ステートメントが実行されます。代わりに、匿名関数の呼び出し時に x の値がキャプチャされ、最新の値が確実に出力されます。
ポインターの使用:
var x int defer func() { fmt.Println(&x) }()
このアプローチでは、x へのポインターを使用します。遅延関数のパラメータとして。 「defer」ステートメントが実行されると、x の値ではなくポインターのみが評価されます。遅延関数が呼び出されると、ポインターを介して x の現在値にアクセスします。
カスタム タイプの使用:
type MyInt int func (m *MyInt) String() string { return strconv.Itoa(int(*m)) } var x MyInt defer fmt.Println(&x)
この解決策はポインターのアプローチに似ていますが、String() メソッドを実装するカスタム型 (MyInt) を使用します。 String() を実装することで、x の値をどのように出力するかを制御できます。
スライスの使用:
var x []int defer fmt.Println(x)
スライスとはGo の記述子の型。これは、その値が基になる配列への参照であることを意味します。スライスを延期すると、実際の配列要素ではなく参照のみが評価されます。その結果、延期後にスライス要素に加えられた変更は、印刷出力に反映されます。
Struct でのラップ:
type Wrapper struct { Value int } var x Wrapper defer fmt.Println(&x)
このアプローチはポインターの使用に似ていますが、構造体内でポインターを逆参照する必要がないように、値を構造体でラップします。遅延関数。
以上が変更された変数を使用して Go で「defer」を正しく使用する方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。