web-dev-qa-db-fra.com

Type de données Pair / Tuple dans Go

En faisant les exercice final du Tour of Go , j'ai décidé qu'il me fallait une file d'attente de (string, int). C'est assez facile:

type job struct {
    url string
    depth int
}

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

Mais cela m’a amené à penser: existe-t-il des types de données paire/Tuple intégrés dans Go? Il existe un support pour renvoyant plusieurs valeurs à partir d'une fonction, mais AFAICT, les multiniveaux de valeurs générés ne sont pas des citoyens de première classe dans le système de types de Go. Est-ce le cas?

En ce qui concerne la partie "qu’avez-vous essayé", la syntaxe évidente (à partir de Python)

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

n'a pas fonctionné.

93
Fred Foo

Il n'y a pas de type de tuples dans Go, et vous avez raison, les multiples valeurs renvoyées par les fonctions ne représentent pas un objet de première classe.

La réponse de Nick montre comment vous pouvez faire quelque chose de similaire qui traite des types arbitraires en utilisant interface{}. (J'aurais peut-être utilisé un tableau plutôt qu'une structure pour le rendre indexable comme un tuple, mais l'idée clé est le interface{} type)

Mon autre réponse montre comment vous pouvez faire quelque chose de similaire qui évite de créer un type en utilisant des structures anonymes.

Ces techniques ont certaines propriétés des n-uplets, mais non, ce ne sont pas des n-uplets.

45
Sonia

Tu peux le faire. Cela semble plus verbeux qu'un tuple, mais c'est une grande amélioration parce que vous obtenez une vérification de type.

Édition: extrait remplacé par un exemple de travail complet, selon la suggestion de Nick. Lien du terrain de jeu: 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}
}

Les structures et champs anonymes conviennent aux solutions rapides et sales comme celle-ci. Cependant, dans tous les cas sauf les plus simples, vous feriez mieux de définir une structure nommée comme vous le faisiez.

75
Sonia

Tu pourrais faire quelque chose comme ça si tu voulais

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

Cependant, je pense que ce que vous avez déjà est parfaitement idiomatique et que la structure décrit parfaitement vos données, ce qui constitue un gros avantage par rapport à l'utilisation de simples nuplets.

27
Nick Craig-Wood