ホームページ >バックエンド開発 >Golang >ローカル変数の変更に対処するときに Go で Defer を正しく使用するにはどうすればよいですか?

ローカル変数の変更に対処するときに Go で Defer を正しく使用するにはどうすればよいですか?

Susan Sarandon
Susan Sarandonオリジナル
2024-12-10 13:55:14180ブラウズ

How to Correctly Use Defer in Go When Dealing with Changing Local Variables?

Defer 使用法の明確化: 最終的な変数値の出力

Go では、defer キーワードを使用して、関数が実行される直前に実行されるようにスケジュールできます。周囲の関数が戻ります。ただし、遅延関数が周囲の関数内で変更される可能性のあるローカル変数を使用する場合は、正しい値が使用されるように特別な注意を払う必要があります。

次の関数を考えてみましょう:

func printNumbers() {
    var x int

    defer fmt.Println(x)

    for i := 0; i < 5; i++ {
        x++
    }
}

言語仕様に従って、defer ステートメントが実行されると、ローカル変数が評価され、新たに保存されます。ただし、実際の関数は後になるまで呼び出されません。この場合、defer ステートメントが実行されるとき、x の値は 0 であるため、deferred 関数が呼び出されたときに 0 が出力されます。

この問題を解決するには、いくつかの方法のいずれかを使用できます。

1.匿名関数の場合:

defer func() { fmt.Println(x) }()

これは、x の現在値をキャプチャする匿名関数を使用します。匿名関数が呼び出されると、周囲の関数で x が変更された場合でも、キャプチャされた値が使用されます。

2.ポインタの場合:

var x int
defer Print(&x)

x へのポインタを使用し、ポイントされた値を出力する関数を延期できます。ポインタ値は defer ステートメントの実行時に評価されますが、指定された値は deferred 関数が呼び出されるまで評価されないため、これが機能します。

3.カスタム タイプの場合:

type MyInt int
func (m *MyInt) String() string { return strconv.Itoa(int(*m)) }
var x MyInt
defer fmt.Println(&x)

ここでは、fmt.Stringer インターフェイスを実装するカスタム タイプ MyInt を作成し、値の出力方法を指定できるようにします。 &x が出力されると、String メソッドが呼び出され、ポイントされた値の文字列表現が返されます。

4.ラッピング:

x := []int{0}
defer fmt.Println(x)

変数をスライスでラップすると、スライスの内容を出力する関数を延期できます。スライス記述子は defer ステートメントの実行時に評価されますが、基礎となる配列は deferred 関数が呼び出されるまで評価されません。

defer 関数で使用されている変数は、次のパラメータであってはいけないことを覚えておくことが重要です。 defer ステートメントの実行時にパラメーターが評価されるため、遅延関数自体。

以上がローカル変数の変更に対処するときに Go で Defer を正しく使用するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。