ประเภทข้อมูล Pair / tuple ใน Go


118

ในขณะที่ออกกำลังกายครั้งสุดท้ายของ Tour of Goฉันตัดสินใจว่าฉันต้องการคิวคู่( string, int) ง่ายพอ:

type job struct {
    url string
    depth int
}

queue := make(chan job)
queue <- job{url, depth}

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

สำหรับส่วน "คุณได้ลองอะไรบ้าง" ไวยากรณ์ที่ชัดเจน (จาก POV ของโปรแกรมเมอร์ Python)

queue := make(chan (string, int))

ไม่ได้ผล

คำตอบ:


57

ไม่มีประเภททูเปิลใน Go และคุณถูกต้องค่าหลายค่าที่ส่งกลับโดยฟังก์ชันไม่ได้แสดงถึงออบเจ็กต์ชั้นหนึ่ง

คำตอบของ Nick แสดงให้เห็นว่าคุณสามารถทำสิ่งที่คล้ายกันซึ่งจัดการกับประเภทinterface{}ใดก็ได้ (ฉันอาจใช้อาร์เรย์มากกว่าโครงสร้างเพื่อให้สามารถจัดทำดัชนีได้เหมือนทูเปิล แต่แนวคิดหลักคือinterface{}ประเภท)

คำตอบอื่นของฉันแสดงให้เห็นว่าคุณสามารถทำสิ่งที่คล้ายกันได้อย่างไรซึ่งจะหลีกเลี่ยงการสร้างประเภทโดยใช้โครงสร้างที่ไม่ระบุตัวตน

เทคนิคเหล่านี้มีคุณสมบัติบางอย่างของสิ่งทอ แต่ไม่ไม่ใช่สิ่งเหล่านี้


91

คุณสามารถทำได้ มันดูมีคำศัพท์มากกว่าทูเพิล แต่เป็นการปรับปรุงครั้งใหญ่เพราะคุณได้รับการตรวจสอบประเภท

แก้ไข: แทนที่ตัวอย่างด้วยตัวอย่างการทำงานที่สมบูรณ์ตามคำแนะนำของ Nick ลิงค์สนามเด็กเล่น: http://play.golang.org/p/RNx_otTFpk

package main

import "fmt"

func main() {
    queue := make(chan struct {string; int})
    go sendPair(queue)
    pair := <-queue
    fmt.Println(pair.string, pair.int)
}

func sendPair(queue chan struct {string; int}) {
    queue <- struct {string; int}{"http:...", 3}
}

โครงสร้างและฟิลด์ที่ไม่ระบุชื่อเหมาะสำหรับการแก้ปัญหาที่รวดเร็วและสกปรกเช่นนี้ สำหรับทุกกรณียกเว้นกรณีที่ง่ายที่สุดคุณควรกำหนดโครงสร้างที่มีชื่อเช่นเดียวกับที่คุณทำ


9
คุณน่าจะอธิบายวิธีดึงค่าออกมาจากสมาชิกของโครงสร้างที่ไม่ระบุตัวตนได้เพราะฉันคิดว่ามันไม่ชัดเจนสำหรับมือใหม่!
Nick Craig-Wood

9
อย่างไรก็ตามจะใช้ไม่ได้หากมีหลายช่องที่มีประเภทเดียวกัน
newacct

1
คุณสามารถตั้งชื่อเขตข้อมูลในโครงสร้างแบบไม่ระบุตัวตนได้คุณเพียงแค่ต้องตรวจสอบให้แน่ใจว่าเขตข้อมูลนั้นได้รับการตั้งชื่อในลักษณะเดียวกับที่แต่ละแห่งที่คำจำกัดความของโครงสร้างที่ไม่ระบุชื่อปรากฏขึ้น (สามครั้งในตัวอย่างนี้) เขตข้อมูลที่ไม่ระบุชื่อจะง่ายกว่าหากคุณสามารถหลีกเลี่ยงได้ .
Sonia

5
คำตอบคือ "ไม่มีไม่มีทูเพิล"?
Fred Foo

37

คุณสามารถทำสิ่งนี้ได้หากต้องการ

package main

import "fmt"

type Pair struct {
    a, b interface{}
}

func main() {
    p1 := Pair{"finished", 42}
    p2 := Pair{6.1, "hello"}
    fmt.Println("p1=", p1, "p2=", p2)
    fmt.Println("p1.b", p1.b)
    // But to use the values you'll need a type assertion
    s := p1.a.(string) + " now"
    fmt.Println("p1.a", s)
}

อย่างไรก็ตามฉันคิดว่าสิ่งที่คุณมีอยู่แล้วเป็นสำนวนที่สมบูรณ์แบบและโครงสร้างอธิบายข้อมูลของคุณได้อย่างสมบูรณ์แบบซึ่งเป็นข้อได้เปรียบที่ยิ่งใหญ่กว่าการใช้ tuples ธรรมดา

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