Apakah peta diteruskan dengan nilai atau referensi di Go?

94

Apakah peta diteruskan dengan nilai atau referensi di Go?

Itu selalu mungkin untuk mendefinisikan fungsi sebagai berikut, tetapi apakah ini berlebihan?

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

Pertanyaan yang sama untuk nilai pengembalian. Haruskah saya mengembalikan pointer ke peta, atau mengembalikan peta sebagai nilai?

Maksudnya tentu untuk menghindari penyalinan data yang tidak perlu.

chmike
sumber
4
blog.golang.org/go-maps-in-action : Jenis peta adalah jenis referensi, seperti pointer atau irisan, sehingga nilai m di atas adalah nihil; itu tidak menunjuk ke peta yang diinisialisasi. Peta nil berperilaku seperti peta kosong saat membaca, tetapi upaya untuk menulis ke peta nil akan menyebabkan panik runtime; jangan lakukan itu. Untuk menginisialisasi peta, gunakan fungsi make
bawaan
2
Semua yang ada di Go diteruskan oleh nilai. Beberapa nilai kebetulan adalah penunjuk, atau struktur yang berisi penunjuk. (Anda mungkin menginginkan a *mapdalam beberapa kasus, jika Anda perlu menetapkan kembali nilai peta di sebuah alamat)
JimB
mh-cbon, tidak ada tipe referensi di Go.
Inanc Gumus
@ mh-cbon Saya tidak berbicara tentang jenis referensi. Saya bertanya apakah peta dilewatkan oleh referensi, yang setara dengan menanyakan apakah alamat peta dilewatkan sebagai argumen atau "salinan" peta (dilewatkan oleh nilai).
chmike
1
@ mh-cbon Tepatnya, peta adalah penunjuk ke hmap.
Inanc Gumus

Jawaban:

83

Di utas ini Anda akan menemukan jawaban Anda:

Golang: Mengakses peta menggunakan referensinya

Anda tidak perlu menggunakan penunjuk dengan peta.

Tipe peta adalah tipe referensi, seperti pointer atau irisan [1]

Jika Anda perlu mengubah Sesi, Anda dapat menggunakan pointer:

map[string]*Session

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

Boris Le Méec
sumber
16
Untuk menghindari pitfals, ketahuilah bahwa peta hanya diteruskan oleh referensi setelah diinisialisasi , dan ketika diinisialisasi ulang di dalam suatu fungsi, referensi asli tidak akan diperbarui. Berikut ini contoh ilustrasi taman bermain: play.golang.org/p/Q6vrAmmJWR6 Atau artikel lengkap oleh Dave Cheny dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Sindre Myren
19

Berikut adalah beberapa bagian dari Jika peta bukan variabel referensi, apakah itu? oleh Dave Cheney:

Nilai peta adalah penunjuk ke runtime.hmapstruktur.

dan kesimpulan:

Kesimpulan

Peta, seperti saluran, tetapi tidak seperti irisan, hanyalah penunjuk ke jenis waktu proses. Seperti yang Anda lihat di atas, peta hanyalah penunjuk ke sebuah runtime.hmap struktur.

Peta memiliki semantik penunjuk yang sama dengan nilai penunjuk lainnya di program Go. Tidak ada keajaiban kecuali penulisan ulang sintaks peta oleh kompilator menjadi panggilan ke fungsi di runtime/hmap.go.

Dan sedikit menarik tentang sejarah / penjelasan mapsintaks:

Jika peta adalah penunjuk, bukankah seharusnya begitu *map[key]value?

Ini adalah pertanyaan bagus jika peta adalah nilai penunjuk, mengapa ekspresi make(map[int]int)mengembalikan nilai dengan tipe map[int]int. Bukankah seharusnya itu mengembalikan *map[int]int? Ian Taylor menjawab ini baru-baru dalam golang-kacang benang 1 .

Dulu, apa yang kita sebut peta sekarang ditulis sebagai petunjuk, jadi Anda menulis *map[int]int. Kami menjauh dari itu ketika kami menyadari bahwa tidak ada yang pernah menulis maptanpa menulis *map.

Bisa dibilang mengganti nama tipe dari *map[int]intmenjadi map[int]int, meski membingungkan karena tipenya tidak terlihat seperti pointer, kurang membingungkan daripada nilai berbentuk pointer yang tidak dapat dirujuk.

Akavall
sumber
3

Tidak. Peta adalah referensi secara default.

    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
        // -----------------------

    }

Dari Golang Blog-

Tipe peta adalah tipe referensi, seperti pointer atau irisan, sehingga nilai m di atas adalah nil; itu tidak menunjuk ke peta yang diinisialisasi. Peta nil berperilaku seperti peta kosong saat membaca, tetapi upaya untuk menulis ke peta nil akan menyebabkan panik runtime; jangan lakukan itu. Untuk menginisialisasi peta, gunakan fungsi make bawaan:

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

Code Snippet Link Mainkan dengannya.

alamin
sumber