2012-12-02 19 views
50

Durante l'esecuzione dello final exercise of the Tour of Go, ho deciso che avevo bisogno di una coda di coppie (string, int). Questo è abbastanza facile:Tipo di dati coppia/tupla in Go

type job struct { 
    url string 
    depth int 
} 

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

Ma questo mi ha fatto pensare: ci sono built-in coppia/tipi di dati tuple in Go? È disponibile il supporto per returning multiple values da una funzione, ma AFAICT, le tuple a più valori prodotte non sono cittadini di prima classe nel sistema di tipi di Go. È questo il caso?

quanto riguarda la parte "che cosa hai provato", la sintassi evidente (da punto di vista di un programmatore Python)

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

non ha funzionato.

risposta

23

Non esiste alcun tipo di tupla in Go e, se si è corretti, i valori multipli restituiti dalle funzioni non rappresentano un oggetto di prima classe.

La risposta di Nick mostra come è possibile eseguire un'operazione simile che gestisca tipi arbitrari utilizzando l'interfaccia {}. (Avrei potuto usare un array piuttosto che una struct per renderlo indicizzabile come una tupla, ma l'idea chiave è il tipo di interfaccia {})

Un'altra mia risposta mostra come puoi fare qualcosa di simile che evita di creare un tipo usando le strutture anonime.

Queste tecniche hanno alcune proprietà di tuple, ma no, non sono tuple.

54

È possibile farlo. Sembra più prolisso di una tupla, ma è un grande miglioramento perché ottieni il controllo del testo.

Modifica: snippet sostituito con un esempio operativo completo, seguendo il suggerimento di Nick. Link Playground: 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} 
} 

le strutture anonime e campi vanno bene per le soluzioni di rapido e sporco come questo. Per tutti, tranne i casi più semplici, farei meglio a definire una struttura denominata proprio come hai fatto tu.

+7

Probabilmente dovresti descrivere come ottenere i valori dai membri della struttura anonima perché non penso che sia ovvio per un principiante! –

+6

tuttavia, questo non funzionerà se ci sono più campi con lo stesso tipo – newacct

+1

Puoi avere campi con nome in una struttura anonima, devi solo assicurarti che i campi siano nominati nello stesso modo in cui ogni posto visualizza la definizione di struttura anonima (tre volte in questo esempio.) I campi anonimi sono più facili se riesci a farla franca. – Sonia

15

Si potrebbe fare qualcosa di simile se si voleva

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

Tuttavia penso che quello che hai già è perfettamente idiomatica e struct descrive i dati perfettamente che è un grande vantaggio rispetto all'utilizzo di tuple pianura.