ホームページ > バックエンド開発 > Golang > Go の「defer」ステートメントは変数評価をどのように処理しますか?また、予期しない動作に対する回避策は何ですか?

Go の「defer」ステートメントは変数評価をどのように処理しますか?また、予期しない動作に対する回避策は何ですか?

Linda Hamilton
リリース: 2024-12-18 13:32:15
オリジナル
284 人が閲覧しました

How Does Go's `defer` Statement Handle Variable Evaluation, and What Workarounds Exist for Unexpected Behavior?

遅延使用法の明確化

Go で関数の実行を遅延する場合、評価動作を理解することが重要です。仕様に記載されているように、関数のパラメータと値は、defer ステートメントが検出されるとすぐに評価されます。これにより、特に関数内で変更される変数で defer を使用する場合、予期しない結果が生じる可能性があります。

問題のあるケース

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

func printNumbers() {
    var x int
    defer fmt.Println(x)

    for i := 0; i < 5; i++ {
        x++
    }
}
ログイン後にコピー

この関数の目的は、関数の実行が終了したときに x の最終値 (5) を出力することです。ただし、defer ステートメント中に x が即座に評価されるため、代わりにゼロが出力されます。

代替ソリューション

この問題に対処するために、いくつかの代替ソリューションが存在します。

1.匿名関数:

元の関数を延期する代わりに、x の現在値をキャプチャして出力する匿名関数を作成します。

func printNumbers() {
    var x int
    defer func() { fmt.Println(x) }()

    for i := 0; i < 5; i++ {
        x++
    }
}
ログイン後にコピー

2.ポインタ:

実際の値を延期するには、x へのポインタを使用します。 defer ステートメントではアドレスのみが評価されるため、x の最終値が出力されます。

func printNumbers() {
    var x int
    defer fmt.Println(&x)

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

func Print(i *int) {
    fmt.Println(*i)
}
ログイン後にコピー

3.カスタム タイプ:

fmt.Stringer を実装するカスタム タイプを作成します。これにより、型で出力方法を定義でき、正しい値が表示されるようになります。

type MyInt int

func (m *MyInt) String() string {
    return strconv.Itoa(int(*m))
}

func printNumbers() {
    var x MyInt
    defer fmt.Println(&x)

    for i := 0; i < 5; i++ {
        x++
    }
}
ログイン後にコピー

4.スライス:

スライスは、基礎となるデータ構造を参照する記述子です。変数を含むスライスを遅延させると、最終的に変更された値が出力されます。

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

    for i := 0; i < 5; i++ {
        x[0]++
    }
}
ログイン後にコピー

結論

遅延関数実行の即時評価動作を理解することは、defer を効果的に使用するために不可欠です。提供されるソリューションは、関数の実行を延期するときに意図した値が確実に出力されるようにするためのさまざまなアプローチを示しています。

以上がGo の「defer」ステートメントは変数評価をどのように処理しますか?また、予期しない動作に対する回避策は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート