ホームページ > バックエンド開発 > Golang > Go で非ポインタの「interface{}」パラメータを指定した「json.Unmarshal」が予期しない結果を引き起こすのはなぜですか?

Go で非ポインタの「interface{}」パラメータを指定した「json.Unmarshal」が予期しない結果を引き起こすのはなぜですか?

Mary-Kate Olsen
リリース: 2024-12-04 20:19:12
オリジナル
273 人が閲覧しました

Why Does `json.Unmarshal` with a Non-Pointer `interface{}` Parameter Produce Unexpected Results in Go?

インターフェース{} タイプの誤解: 複雑さを明らかにする

Go では、インターフェース{} タイプは柔軟性と複雑さの両方を提供します。ただし、不可解な例で示すように、その性質を誤解すると、予期しない結果が生じる可能性があります。

非ポインタ型をインターフェース パラメータとして関数に渡し、それに json.Unmarshal を使用しようとすると、結果は驚くべきものになる可能性があります。以下の例は、この動作を示しています。

package main

import (
    "encoding/json"
    "fmt"
)

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)
}

type Test struct {
    Foo string
}

func main() {
    test(Test{})
}
ログイン後にコピー

出力:

main.Test
*interface {}
map[string]interface {}
ログイン後にコピー

謎の解明

混乱はインターフェイスの性質に起因します{}。これは単なる型のないコンテナではなく、(値、型) ペアのラッパーです。インターフェイスは具体的な値とその型への参照を保存します。

json.Unmarshal は入力としてインターフェイスの値を受け取るため、i を直接渡すことができます。{} (&i と同様に) そのアドレスを取得しようとすることは不要です。

ポインターとインターフェイス

ただし、i にポインター以外の値が含まれている場合、json.Unmarshal はチャレンジ。パッケージは非ポインタにアンマーシャリングできないため、interface{} 型の新しい値を作成します。これにより、タイプを選択できます。デフォルトは、map[string]interface{} です。

正しいシナリオ

ポインタ シナリオの場合、引数として &i を渡します。 json.Unmarshal がポインタを逆参照して *Test 値を含むインターフェース値を見つけるため、機能します。{}ポインターにより、アンマーシャリングが正しい型に行われることが保証されます。

結論

これらの混乱を避けるために、インターフェイスへのポインターの使用は控えてください。代わりに、インターフェイス内にポインタを「配置」し、それらを直接渡します。インターフェースとポインタの間の相互作用を理解することで、開発者は予期しない結果を回避し、Go の型システムを効果的に活用できます。

以上がGo で非ポインタの「interface{}」パラメータを指定した「json.Unmarshal」が予期しない結果を引き起こすのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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