>백엔드 개발 >Golang >포인터가 아닌 `interface{}` 매개변수가 포함된 `json.Unmarshal`이 Go에서 예상치 못한 결과를 생성하는 이유는 무엇입니까?

포인터가 아닌 `interface{}` 매개변수가 포함된 `json.Unmarshal`이 Go에서 예상치 못한 결과를 생성하는 이유는 무엇입니까?

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-12-04 20:19:12266검색

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

Unveiling the Mystery

혼란은 인터페이스의 특성에서 비롯됩니다. {}. 이는 단순히 유형이 없는 컨테이너가 아니라 (값, 유형) 쌍에 대한 래퍼입니다. 인터페이스는 구체적인 값과 해당 유형에 대한 참조를 저장합니다.

json.Unmarshal은 인터페이스{} 값을 입력으로 사용하므로 i를 직접 전달할 수 있습니다. (&i와 마찬가지로) 해당 주소를 가져오려는 시도는 불필요합니다.

포인터 및 인터페이스

그러나 i에 포인터가 아닌 값이 포함되어 있으면 json.Unmarshal은 다음과 같은 문제에 직면합니다. 도전. 패키지는 비포인터로 역마샬링할 수 없으므로 인터페이스{} 유형의 새 값을 생성합니다. 이를 통해 기본적으로 map[string]interface{}로 설정된 유형을 선택할 수 있습니다.

올바른 시나리오

포인터 시나리오의 경우 &i를 인수로 전달 json.Unmarshal이 포인터를 역참조하여 *Test 값이 포함된 인터페이스 값을 찾기 때문에 작동합니다. 포인터는 올바른 유형으로 역마샬링이 발생하도록 보장합니다.

결론

이러한 혼란을 피하려면 인터페이스에 대한 포인터를 사용하지 마십시오. 대신, 인터페이스 내에 포인터를 "배치"하고 직접 전달하십시오. 인터페이스와 포인터 간의 상호 작용을 이해함으로써 개발자는 예상치 못한 결과를 방지하고 Go의 유형 시스템을 효과적으로 활용할 수 있습니다.

위 내용은 포인터가 아닌 `interface{}` 매개변수가 포함된 `json.Unmarshal`이 Go에서 예상치 못한 결과를 생성하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.