ホームページ >バックエンド開発 >Golang >「interface{}」の使用時に「json.Unmarshal」が予期せず構造体を変更するのはなぜですか?

「interface{}」の使用時に「json.Unmarshal」が予期せず構造体を変更するのはなぜですか?

Barbara Streisand
Barbara Streisandオリジナル
2024-12-12 19:53:11225ブラウズ

Why Does `json.Unmarshal` Unexpectedly Change My Struct When Using `interface{}`?

Go のインターフェースに関する誤解{} タイプ

背景

Go プログラミングの重要な側面であるインターフェース{} タイプにより、次の動的な処理が可能になります。

の予期せぬバグjson.Unmarshal

interface{} を関数パラメータとして使用し、json.Unmarshal で問題が発生した場合によくある誤解が生じます。次のコード スニペットは、このバグを示しています。

func test(i interface{}) {
    j := []byte(`{ "foo": "bar" }`)
    fmt.Printf("%T\n", i)
    fmt.Printf("%T\n", &i)
    json.Unmarshal(j, &i)
    fmt.Printf("%T\n", i)
}

func main() {
    test(Test{})
}

type Test struct {
    Foo string
}

このコードを実行すると、出力に見られるように、アンマーシャリングされた後、構造体 Test{} が予期せず map[string]interface{} に変換されます。

main.Test
*interface {}
map[string]interface {}

誤解を理解する

誤解は、インターフェース タイプの性質にあります。{}これは、一部の人が想定しているような空のコンテナではなく、値と型のペアのラッパーです。非ポインタ Test{} が test() に渡されると、json.Unmarshal 関数はポインタを期待し、代わりに新しい map[string]interface{} 値を作成します。

この問題を解決するには

func test(i interface{}) {
    j := []byte(`{ "foo": "bar" }`)
    fmt.Printf("%T\n", i)
    fmt.Printf("%T\n", &i)
    json.Unmarshal(j, i)
    fmt.Printf("%T\n", i)
    fmt.Println(i)
}

func main() {
    test(&Test{})
}

この変更により、ポインタへのポインタが関数に渡されるようになり、 json.Unmarshal は、JSON データを正しくアンマーシャルします。

結論

予期しない動作を避けるために、interface{} を慎重に使用する必要があることを覚えておくことが重要です。効果的な Go 開発には、その基礎となる実装と json.Unmarshal などの関数への影響を理解することが不可欠です。

以上が「interface{}」の使用時に「json.Unmarshal」が予期せず構造体を変更するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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