แผนที่ส่งผ่านค่าหรือโดยการอ้างอิงใน Go?


94

แผนที่ส่งผ่านค่าหรือการอ้างอิงใน Go หรือไม่?

เป็นไปได้เสมอที่จะกำหนดฟังก์ชันดังต่อไปนี้ แต่นี่เป็นการ overkill หรือไม่?

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

คำถามเดียวกันสำหรับค่าตอบแทน ฉันควรส่งตัวชี้กลับไปที่แผนที่หรือส่งคืนแผนที่เป็นค่า?

แน่นอนว่ามีเจตนาที่จะหลีกเลี่ยงการคัดลอกข้อมูลที่ไม่จำเป็น


4
blog.golang.org/go-maps-in-action : ประเภทแผนที่เป็นประเภทอ้างอิงเช่นพอยน์เตอร์หรือสไลซ์ดังนั้นค่าของ m ด้านบนจึงเป็นศูนย์ มันไม่ได้ชี้ไปที่แผนที่เริ่มต้น แผนที่ศูนย์ทำงานเหมือนแผนที่ว่างเปล่าเมื่ออ่าน แต่ความพยายามที่จะเขียนลงในแผนที่ศูนย์จะทำให้รันไทม์ตื่นตระหนก อย่าทำอย่างนั้น ในการเริ่มต้นแผนที่ให้ใช้ฟังก์ชัน make ในตัว
mh-cbon

2
ทุกอย่างใน Go ผ่านไปด้วยคุณค่า ค่าบางค่าเกิดขึ้นเพื่อเป็นพอยน์เตอร์หรือโครงสร้างที่มีพอยน์เตอร์ (คุณอาจต้องการ*mapในบางกรณีหากคุณจำเป็นต้องกำหนดค่าแผนที่ใหม่ตามที่อยู่)
JimB

mh-cbon ไม่มีประเภทอ้างอิงใน Go
Inanc Gumus

@ mh-cbon ฉันไม่ได้พูดถึงประเภทการอ้างอิง ฉันถามว่าแผนที่ถูกส่งผ่านโดยการอ้างอิงหรือไม่ซึ่งเทียบเท่ากับการถามว่าที่อยู่ของแผนที่ถูกส่งผ่านเป็นอาร์กิวเมนต์หรือ "สำเนา" ของแผนที่ (ส่งผ่านด้วยค่า)
chmike

1
@ mh-cbon แน่นอนแผนที่เป็นตัวชี้ไปยัง hmap
Inanc Gumus

คำตอบ:


83

ในหัวข้อนี้คุณจะพบคำตอบของคุณ:

Golang: การเข้าถึงแผนที่โดยใช้ข้อมูลอ้างอิง

คุณไม่จำเป็นต้องใช้ตัวชี้กับแผนที่

ประเภทแผนที่คือประเภทอ้างอิงเช่นพอยน์เตอร์หรือสไลซ์ [1]

หากคุณต้องการเปลี่ยนเซสชันคุณสามารถใช้ตัวชี้:

map[string]*Session

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


16
เพื่อหลีกเลี่ยงหลุมพรางใด ๆ โปรดทราบว่าแผนที่จะถูกส่งผ่านโดยการอ้างอิงเมื่อเริ่มต้นแล้วเท่านั้นและเมื่อเริ่มต้นใหม่ภายในฟังก์ชันการอ้างอิงเดิมจะไม่ได้รับการอัปเดต นี่คือตัวอย่างสนามเด็กเล่นที่มีภาพประกอบ: play.golang.org/p/Q6vrAmmJWR6 หรือบทความเต็มโดย Dave Cheny dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Sindre Myren

19

นี่คือบางส่วนจากถ้าแผนที่ไม่ใช่ตัวแปรอ้างอิงมันคืออะไร? โดย Dave Cheney:

ค่าแผนที่เป็นตัวชี้ไปยังruntime.hmapโครงสร้าง

และข้อสรุป:

สรุป

แผนที่เหมือนช่องทาง แต่ต่างจากสไลซ์เป็นเพียงตัวชี้ไปยังประเภทรันไทม์ ดังที่คุณเห็นด้านบนแผนที่เป็นเพียงตัวชี้ไปยังruntime.hmap โครงสร้าง

แผนที่มีความหมายของตัวชี้เหมือนกับค่าตัวชี้อื่น ๆ ในโปรแกรม Go ไม่มีเวทมนตร์ใดที่จะบันทึกการเขียนไวยากรณ์แผนที่ใหม่โดยคอมไพเลอร์ในการเรียกใช้ฟังก์ชันในruntime/hmap.go.

และสิ่งที่น่าสนใจเกี่ยวกับประวัติ / คำอธิบายของmapไวยากรณ์:

ถ้าแผนที่เป็นตัวชี้ไม่ควร*map[key]value?

มันเป็นคำถามที่ดีว่าถ้าแผนที่เป็นค่าตัวชี้ทำไมไม่แสดงออกกลับค่ากับชนิดmake(map[int]int) map[int]intไม่ควรคืน a *map[int]int? เอียนเทย์เลอร์ ตอบเมื่อเร็ว ๆ นี้ใน golang ถั่วด้าย1

*map[int]intในวันแรกมากสิ่งที่เราเรียกแผนที่ในขณะนี้ถูกเขียนเป็นตัวชี้เพื่อให้คุณเขียน เราย้ายออกไปจากที่ว่าเมื่อเราตระหนักว่าไม่มีใครเคยเขียนโดยไม่ต้องเขียนmap*map

การเปลี่ยนชื่อประเภทจากเป็นเป็น*map[int]intไปmap[int]intได้ยากในขณะที่เกิดความสับสนเนื่องจากชนิดไม่เหมือนตัวชี้มีความสับสนน้อยกว่าค่ารูปตัวชี้ซึ่งไม่สามารถยกเลิกการอ้างอิงได้


3

ไม่แผนที่เป็นข้อมูลอ้างอิงโดยค่าเริ่มต้น

    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-

ประเภทแผนที่คือประเภทอ้างอิงเช่นพอยน์เตอร์หรือสไลซ์ดังนั้นค่าของ m ด้านบนจึงเป็นศูนย์ มันไม่ได้ชี้ไปที่แผนที่เริ่มต้น แผนที่ศูนย์ทำงานเหมือนแผนที่ว่างเปล่าเมื่ออ่าน แต่การพยายามเขียนลงในแผนที่ศูนย์จะทำให้รันไทม์ตื่นตระหนก อย่าทำอย่างนั้น ในการเริ่มต้นแผนที่ให้ใช้ฟังก์ชันสร้างในตัว:

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

Code Snippet Linkเล่นกับมัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.