Typ danych pary / krotki w Go

118

Wykonując ostatnie ćwiczenie Tour of Go , zdecydowałem, że potrzebuję kolejki ( string, int) par. To dość proste:

type job struct {
    url string
    depth int
}

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

Ale to dało mi do myślenia: czy w Go są wbudowane typy danych typu para / krotka? Istnieje wsparcie dla zwracania wielu wartości z funkcji, ale AFAICT, wyprodukowane krotki wielu wartości nie są obywatelami pierwszej klasy w systemie typów Go. Czy tak jest?

Jeśli chodzi o część „czego próbowałeś”, oczywista składnia (z punktu widzenia programisty Pythona)

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

nie zadziałało.

Fred Foo
źródło

Odpowiedzi:

57

W Go nie ma typu krotki i masz rację, wiele wartości zwracanych przez funkcje nie reprezentuje obiektu pierwszej klasy.

Odpowiedź Nicka pokazuje, jak można zrobić coś podobnego, który obsługuje dowolne typy przy użyciu interface{}. (Mogłem użyć tablicy zamiast struktury, aby uczynić ją indeksowalną jak krotkę, ale kluczową ideą jest interface{}typ)

Moja druga odpowiedź pokazuje, jak można zrobić coś podobnego, unikając tworzenia typu przy użyciu struktur anonimowych.

Te techniki mają pewne właściwości krotek, ale nie, to nie są krotki.

Sonia
źródło
91

Możesz to zrobić. Wygląda bardziej rozwlekle niż krotka, ale jest to duża poprawa, ponieważ sprawdzasz typ.

Edycja: zastąpiono fragment kodu kompletnym działającym przykładem, zgodnie z sugestią Nicka. Link do placu zabaw: 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}
}

Anonimowe struktury i pola nadają się do takich szybkich i brudnych rozwiązań. Jednak we wszystkich przypadkach, z wyjątkiem najprostszych, lepiej byłoby zdefiniować nazwaną strukturę, tak jak to zrobiłeś.

Sonia
źródło
9
Powinieneś prawdopodobnie opisać, jak uzyskać wartości z anonimowych członków struktury, ponieważ nie sądzę, aby było to oczywiste dla początkującego!
Nick Craig-Wood
9
jednak to nie zadziała, jeśli istnieje wiele pól tego samego typu
newacct
1
Możesz mieć nazwane pola w strukturze anonimowej, musisz tylko upewnić się, że pola są nazwane tak samo, jak w każdym miejscu pojawia się definicja struktury anonimowej (trzy razy w tym przykładzie). Pola anonimowe są łatwiejsze, jeśli możesz sobie z tym poradzić .
Sonia
5
Więc odpowiedź brzmi „nie, nie ma typu krotki”?
Fred Foo
37

Mógłbyś zrobić coś takiego, gdybyś chciał

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

Jednak myślę, że to, co już masz, jest idealnie idiomatyczne, a struktura doskonale opisuje twoje dane, co jest dużą zaletą w porównaniu z użyciem zwykłych krotek.

Nick Craig-Wood
źródło