Go에서 맵이 값으로 전달됩니까, 아니면 참조로 전달됩니까?


89

지도가 Go에서 값이나 참조로 전달됩니까?

항상 다음과 같이 함수를 정의 할 수 있지만 이것이 과잉입니까?

func foo(dat *map[string]interface{}) {...}

반환 값에 대한 동일한 질문입니다. 지도에 대한 포인터를 반환해야합니까, 아니면지도를 값으로 반환해야합니까?

의도는 물론 불필요한 데이터 복사를 방지하는 것입니다.


4
blog.golang.org/go-maps-in-action :지도 유형은 포인터 또는 슬라이스와 같은 참조 유형이므로 위의 m 값은 nil입니다. 초기화 된지도를 가리 키지 않습니다. nil 맵은 읽을 때 빈 맵처럼 동작하지만 nil 맵에 쓰려고하면 런타임 패닉이 발생합니다. 그러지 마. 맵을 초기화하려면 내장 된 make 함수를 사용하십시오
mh-cbon

2
Go의 모든 것은 가치로 전달됩니다. 일부 값은 포인터 또는 포인터를 포함하는 구조 일 수 있습니다. ( *map주소에서 맵 값을 다시 할당해야하는 경우 경우에 따라 a 를 원할 수 있습니다. )
JimB

mh-cbon, Go에는 참조 유형이 없습니다.
Inanc Gumus 2019 년

@ mh-cbon 나는 참조 유형에 대해 이야기하지 않았습니다. 지도가 참조 로 전달 되는지 여부를 묻습니다. 이는지도의 주소가 인수로 전달되는지 또는지도의 "복사본"(값으로 전달됨)으로 전달되는지 묻는 것과 같습니다.
chmike

1
@ mh-cbon 정확히 맵은 hmap에 대한 포인터입니다.
Inanc Gumus

답변:


79

이 스레드에서 답을 찾을 수 있습니다.

Golang : 참조를 사용하여지도에 액세스

지도와 함께 포인터를 사용할 필요가 없습니다.

지도 유형은 포인터 또는 슬라이스와 같은 참조 유형입니다 [1]

세션을 변경해야하는 경우 포인터를 사용할 수 있습니다.

map[string]*Session

https://blog.golang.org/go-maps-in-action


15
pitfals를 방지하려면지도는 초기화 된 후에 만 참조로 전달되며 함수 내에서 다시 초기화 될 때 원래 참조 는 업데이트되지 않습니다. 다음은 놀이터 예시입니다. play.golang.org/p/Q6vrAmmJWR6 또는 Dave Cheny의 전체 기사 dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Sindre Myren

18

다음은 맵이 참조 변수가 아닌 경우 무엇입니까? 작성자 : Dave Cheney :

맵 값은 runtime.hmap구조에 대한 포인터 입니다.

그리고 결론 :

결론

채널과 비슷하지만 슬라이스와는 달리 맵은 런타임 유형에 대한 포인터 일뿐입니다. 위에서 보았 듯이 맵은 runtime.hmap 구조에 대한 포인터 일뿐 입니다.

맵은 Go 프로그램의 다른 포인터 값과 동일한 포인터 의미를 갖습니다. 컴파일러가 .NET의 함수 호출로 맵 구문을 다시 작성하는 것을 저장하는 마술은 없습니다 runtime/hmap.go.

그리고 map구문의 역사 / 설명에 대한 흥미로운 부분 :

지도가 포인터라면, 그렇지 *map[key]value않습니까?

지도가 포인터 값인 경우 표현식 make(map[int]int)이 유형으로 값을 반환하는 이유는 무엇입니까 map[int]int? 반환해야하지 *map[int]int않습니까? Ian Taylor 는 최근 golang-nuts 스레드 1 에서 이에 대해 답변했습니다 .

초창기에는지도라고 부르는 것이 포인터로 작성되었으므로 *map[int]int. 우리는 아무도 글 map을 쓰지 않고 쓴 적이 없다는 것을 깨달았을 때 그것에서 멀어졌습니다 *map.

유형이 포인터처럼 보이지 않기 때문에 혼란 스럽지만 유형을에서 *map[int]int로 이름을 바꾸는 map[int]int것은 역 참조 할 수없는 포인터 모양의 값보다 덜 혼란 스럽습니다.


1

아니요.지도는 기본적으로 참조입니다.

    package main

    import "fmt"

    func mapToAnotherFunction(m map[string]int) {
        m["hello"] = 3
        m["world"] = 4
        m["new_word"] = 5
    }

    // func mapToAnotherFunctionAsRef(m *map[string]int) {
    // m["hello"] = 30
    // m["world"] = 40
    // m["2ndFunction"] = 5
    // }

    func main() {
        m := make(map[string]int)
        m["hello"] = 1
        m["world"] = 2

        // Initial State
        for key, val := range m {
            fmt.Println(key, "=>", val)
        }

        fmt.Println("-----------------------")

        mapToAnotherFunction(m)
        // After Passing to the function as a pointer
        for key, val := range m {
            fmt.Println(key, "=>", val)
        }

        // Try Un Commenting This Line
        fmt.Println("-----------------------")

        // mapToAnotherFunctionAsRef(&m)
        // // After Passing to the function as a pointer
        // for key, val := range m {
        //  fmt.Println(key, "=>", val)
        // }

        // Outputs
        // hello => 1
        // world => 2
        // -----------------------
        // hello => 3
        // world => 4
        // new_word => 5
        // -----------------------

    }

Golang 블로그에서

지도 유형은 포인터 또는 슬라이스와 같은 참조 유형이므로 위의 m 값은 nil입니다. 초기화 된지도를 가리 키지 않습니다. nil 맵은 읽을 때 빈 맵처럼 동작하지만 nil 맵에 쓰려고하면 런타임 패닉이 발생합니다. 그러지 마. 지도를 초기화하려면 내장 된 make 함수를 사용하세요.

// Ex of make function
m = make(map[string]int)

Code Snippet Link 그것을 가지고 놀아 라.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.