Pair / Tuple-Datentyp in Go

118

Während der letzten Übung der Tour of Go entschied ich, dass ich eine Warteschlange mit ( string, int) Paaren brauchte . Das ist einfach genug:

type job struct {
    url string
    depth int
}

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

Aber das brachte mich zum Nachdenken: Gibt es in Go integrierte Pair / Tuple-Datentypen? Es gibt Unterstützung für die Rückgabe mehrerer Werte von einer Funktion, aber AFAICT, die produzierten Tupel mit mehreren Werten, sind keine erstklassigen Bürger im Go-Typsystem. Ist das der Fall?

Was den Teil "Was hast du versucht" betrifft, die offensichtliche Syntax (aus dem POV eines Python-Programmierers)

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

hat nicht funktioniert.

Fred Foo
quelle

Antworten:

57

In Go gibt es keinen Tupeltyp, und Sie haben Recht, die von Funktionen zurückgegebenen Mehrfachwerte stellen kein erstklassiges Objekt dar.

Nicks Antwort zeigt, wie Sie etwas Ähnliches tun können, das mit beliebigen Typen umgeht interface{}. (Ich hätte vielleicht eher ein Array als eine Struktur verwendet, um es wie ein Tupel indizierbar zu machen, aber die Schlüsselidee ist der interface{}Typ)

Meine andere Antwort zeigt, wie Sie etwas Ähnliches tun können, ohne einen Typ mit anonymen Strukturen zu erstellen.

Diese Techniken haben einige Eigenschaften von Tupeln, aber nein, sie sind keine Tupel.

Sonia
quelle
89

Du kannst das. Es sieht wortreicher aus als ein Tupel, aber es ist eine große Verbesserung, weil Sie eine Typprüfung erhalten.

Bearbeiten: Snippet durch vollständiges Arbeitsbeispiel ersetzt, gemäß Nicks Vorschlag. Spielplatz-Link: 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}
}

Anonyme Strukturen und Felder eignen sich gut für schnelle und schmutzige Lösungen wie diese. Für alle außer den einfachsten Fällen ist es jedoch besser, eine benannte Struktur so zu definieren, wie Sie es getan haben.

Sonia
quelle
9
Sie sollten wahrscheinlich beschreiben, wie Sie die Werte aus den anonymen Strukturmitgliedern herausholen können, da ich denke, dass dies für Anfänger nicht offensichtlich ist!
Nick Craig-Wood
9
Dies funktioniert jedoch nicht, wenn mehrere Felder mit demselben Typ vorhanden sind
newacct
1
Sie können benannte Felder in einer anonymen Struktur haben. Sie müssen lediglich sicherstellen, dass die Felder an jeder Stelle, an der die anonyme Strukturdefinition angezeigt wird, gleich benannt werden (in diesem Beispiel dreimal). Anonyme Felder sind einfacher, wenn Sie damit durchkommen .
Sonia
5
Die Antwort lautet also "Nein, es gibt keinen Tupeltyp"?
Fred Foo
37

Sie könnten so etwas tun, wenn Sie wollten

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)
}

Ich denke jedoch, dass das, was Sie bereits haben, vollkommen idiomatisch ist und die Struktur Ihre Daten perfekt beschreibt, was ein großer Vorteil gegenüber der Verwendung einfacher Tupel ist.

Nick Craig-Wood
quelle