ホームページ  >  記事  >  バックエンド開発  >  golang 関数クロージャーのよくある落とし穴

golang 関数クロージャーのよくある落とし穴

PHPz
PHPzオリジナル
2024-04-23 12:45:021005ブラウズ

Go で関数クロージャを使用する場合、落とし穴があります。 変数の共有: 複数のクロージャが同じ変数を参照しているときに変数を変更すると、すべてのクロージャの動作に影響します。変数の型変換: 後でキャプチャ変数の型を別の型に変換すると、予期しない結果が生じる可能性があります。実際には、シーケンスを生成する関数クロージャの問題は、キャプチャされた変数の変更を避けるために各クロージャのローカル変数のコピーを作成することで解決できます。

golang 関数クロージャーのよくある落とし穴

Go における関数クロージャのよくある落とし穴

Go では、クロージャとは、作成時にローカル変数を参照する関数を指します。これによりプログラムに柔軟性がもたらされますが、使用方法を誤ると、予期しない動作やデバッグが困難な問題が発生する可能性もあります。

クロージャー トラップ

一般的な関数クロージャー トラップの一部を次に示します。

1. 変数の共有

When 複数の When クロージャーが参照する同じローカル変数に追加すると、その変数を変更するとすべてのクロージャの動作に影響します。例:

func counter() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

// 两个同时调用的闭包共享计数变量
c1 := counter()
c2 := counter()
c1()
c2()

では、戻り値が予期される 1 と 2 ではなく 2 になります。

2. 変数の型変換

変数の型を後で別の型に変換すると、予期しない動作が発生する可能性があります。例:

func intToString() string {
    i := 42
    return func() string {
        // 会返回一个空字符串,而不是 "42"
        return strconv.Itoa(i)
    }
}

クロージャによってキャプチャされた変数は文字列型に変換されるため、strconv.Itoa() は正しく変換できません。

実際のケース

期待:最大値に達するまで、渡された数値に基づいてシーケンスを生成する関数を作成します。

コード:

func generateSequence(max int) []int {
    seq := []int{}
    i := 0
    return func() int {
        i++
        if i > max {
            return 0
        }
        seq = append(seq, i)
        return i
    }
}

問題: この関数のクロージャは i 変数をキャプチャし、クロージャが呼び出されたときにそれを変更します。ただし、クロージャは呼び出されるたびに新しい i 値を返すことが期待されます。

修正: この問題は、クロージャごとにローカル変数のコピーを作成することで解決できます。

func generateSequence(max int) []int {
    seq := []int{}
    return func() int {
        i := 0
        i++
        if i > max {
            return 0
        }
        seq = append(seq, i)
        return i
    }
}

注: 修正されたコードでは、キャプチャされた i 変数は変更されなくなりますが、毎回新しいコピーが作成されます。

以上がgolang 関数クロージャーのよくある落とし穴の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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