Haritalar Go'da değere göre mi yoksa referans olarak mı aktarılıyor?


94

Haritalar Go'da değer veya referans ile aktarılıyor mu?

Bir işlevi aşağıdaki gibi tanımlamak her zaman mümkündür, ancak bu bir abartı mı?

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

Dönüş değeri için aynı soru. Haritaya bir işaretçi mi yoksa haritayı değer olarak mı döndürmeliyim?

Tabii ki amaç gereksiz veri kopyalarından kaçınmaktır.


4
blog.golang.org/go-maps-in-action : Harita türleri, işaretçiler veya dilimler gibi başvuru türleridir ve bu nedenle yukarıdaki m'nin değeri sıfırdır; başlatılmış bir haritayı göstermez. Sıfır haritası, okurken boş bir harita gibi davranır, ancak sıfır haritaya yazma girişimleri çalışma zamanı paniğine neden olur; bunu yapma. Bir haritayı başlatmak için yerleşik make işlevini kullanın
mh-cbon

2
Go'daki her şey değere göre aktarılır. Bazı değerler işaretçiler veya işaretçiler içeren yapılar olabilir. ( *mapbazı durumlarda harita değerini bir adreste yeniden atamanız gerekirse bir isteyebilirsiniz )
JimB

mh-cbon, Go'da referans türü yoktur.
İnanç Gümüş

@ mh-cbon Bir referans türünden bahsetmiyordum. Bir haritanın referans olarak geçip geçmediğini soruyordum , bu da haritanın adresinin bağımsız değişken olarak mı yoksa haritanın bir "kopyası" olarak mı (değerle aktarıldı) geçirildiğini sormaya eşdeğerdir.
chmike

1
@ mh-cbon Kesinlikle, haritalar hmap için işaretçilerdir.
İnanç Gümüş

Yanıtlar:


83

Bu ileti dizisinde cevabınızı bulacaksınız:

Golang: Referansını kullanarak bir haritaya erişim

Haritalı bir işaretçi kullanmanıza gerek yoktur.

Harita türleri, işaretçiler veya dilimler gibi referans türleridir [1]

Oturumu değiştirmeniz gerekirse, bir işaretçi kullanabilirsiniz:

map[string]*Session

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


16
Herhangi bir pitfalden kaçınmak için, haritaların yalnızca başlatıldıktan sonra referansla aktarıldığını ve bir işlev içinde yeniden başlatıldığında orijinal referansın güncellenmeyeceğini unutmayın. İşte açıklayıcı bir oyun alanı örneği: play.golang.org/p/Q6vrAmmJWR6 Veya tam bir makale Dave Cheny dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Sindre Myren

19

İşte bazı parçaları bir harita, bir referans değişken değilse, nedir? Dave Cheney tarafından:

Bir harita değeri, bir runtime.hmapyapıya bir göstericidir .

ve sonuç:

Sonuç

Haritalar, kanallar gibi, ancak dilimlerin aksine, yalnızca çalışma zamanı türlerine işaret eder. Yukarıda gördüğünüz gibi, harita sadece bir runtime.hmap yapının göstergesidir .

Haritalar, bir Go programındaki diğer işaretçi değerleriyle aynı işaretçi semantiğine sahiptir. Derleyici tarafından harita sözdiziminin içindeki işlev çağrılarına yeniden yazılmasının hiçbir sihri yoktur runtime/hmap.go.

Ve mapsözdiziminin tarihi / açıklaması hakkında ilginç bir parça :

Haritalar işaretçi ise, olması gerekmiyor *map[key]valuemu?

Haritaların işaretçi değerleri olması durumunda ifadenin neden türle birlikte make(map[int]int)bir değer döndürdüğü iyi bir sorudur map[int]int. Bir döndürmesi gerekmez *map[int]intmi? Ian Taylor bir golang-fındık son zamanlarda bu cevap iplik 1 .

İlk günlerde harita dediğimiz şey şimdi işaretçi olarak yazılıyordu, yani siz yazdınız *map[int]int. Hiç mapkimsenin yazmadan yazmadığını fark ettiğimizde bundan uzaklaştık *map.

Türü bir işaretçi gibi görünmediği *map[int]intiçin map[int]intkafa karıştırıcı olsa da, tartışmalı bir şekilde türünün olarak yeniden adlandırılması, referans alınamayan işaretçi şekilli bir değerden daha az kafa karıştırıcıydı.


3

Hayır. Haritalar varsayılan olarak referanstır.

    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 Blog'dan-

Harita türleri, işaretçiler veya dilimler gibi başvuru türleridir ve bu nedenle yukarıdaki m'nin değeri sıfırdır; başlatılmış bir haritayı göstermez. Sıfır haritası, okurken boş bir harita gibi davranır, ancak sıfır haritaya yazma girişimleri çalışma zamanı paniğine neden olur; bunu yapma. Bir haritayı başlatmak için yerleşik make işlevini kullanın:

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

Kod Parçacığı Bağlantısı Onunla oynayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.