Tipo de datos de par / tupla en Go

118

Mientras hacía el ejercicio final del Tour of Go , decidí que necesitaba una cola de ( string, int) pares. Eso es bastante fácil:

type job struct {
    url string
    depth int
}

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

Pero esto me hizo pensar: ¿hay tipos de datos de par / tupla integrados en Go? Existe soporte para devolver múltiples valores de una función, pero AFAICT, las tuplas de múltiples valores producidas no son ciudadanos de primera clase en el sistema de tipos de Go. ¿Es ese el caso?

En cuanto a la parte "¿qué has probado?", La sintaxis obvia (del punto de vista del programador de Python)

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

no funcionó.

Fred Foo
fuente

Respuestas:

57

No hay un tipo de tupla en Go, y está en lo correcto, los múltiples valores devueltos por las funciones no representan un objeto de primera clase.

La respuesta de Nick muestra cómo puede hacer algo similar que maneja tipos arbitrarios usando interface{}. (Podría haber usado una matriz en lugar de una estructura para que sea indexable como una tupla, pero la idea clave es el interface{}tipo)

Mi otra respuesta muestra cómo puede hacer algo similar que evite crear un tipo utilizando estructuras anónimas.

Estas técnicas tienen algunas propiedades de tuplas, pero no, no son tuplas.

Sonia
fuente
91

Puedes hacerlo. Parece más prolijo que una tupla, pero es una gran mejora porque obtiene la verificación de tipos.

Editar: se reemplazó el fragmento con un ejemplo de trabajo completo, siguiendo la sugerencia de Nick. Enlace al patio de juegos: 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}
}

Las estructuras y campos anónimos están bien para soluciones rápidas y sucias como esta. Sin embargo, para todos los casos menos los más simples, sería mejor definir una estructura con nombre como lo hizo.

Sonia
fuente
9
¡Probablemente debería describir cómo obtener los valores de los miembros de estructura anónimos porque no creo que sea obvio para un principiante!
Nick Craig-Wood
9
sin embargo, esto no funcionará si hay varios campos con el mismo tipo
newacct
1
Puede tener campos con nombre en una estructura anónima, solo tiene que asegurarse de que los campos tengan el mismo nombre en cada lugar donde aparece la definición de estructura anónima (tres veces en este ejemplo). Los campos anónimos son más fáciles si puede salirse con la suya .
Sonia
5
Entonces, ¿la respuesta es "no, no hay tipo de tupla"?
Fred Foo
37

Podrías hacer algo como esto si quisieras

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

Sin embargo, creo que lo que ya tiene es perfectamente idiomático y la estructura describe sus datos perfectamente, lo que es una gran ventaja sobre el uso de tuplas simples.

Nick Craig-Wood
fuente