Comment convertir l'interface {} en chaîne?

114

J'utilise docopt pour analyser les arguments de ligne de commande. Cela fonctionne, et il en résulte une carte, telle que

map[<host>:www.google.de <port>:80 --help:false --version:false]

Maintenant, je voudrais concaténer le hostet la portvaleur en une chaîne avec un deux-points entre les deux valeurs. Fondamentalement, quelque chose comme:

host := arguments["<host>"] + ":" + arguments["<port>"]

Malheureusement, cela ne fonctionne pas, car je reçois le message d'erreur:

opération non valide: arguments [""] + ":" (interface de types incompatibles {} et chaîne)

Donc, évidemment, je dois convertir la valeur que j'obtiens de la carte (ce qui est juste interface{}, donc ça peut être n'importe quoi) en une chaîne. Maintenant ma question est, comment puis-je faire cela?

Golo Roden
la source

Réponses:

153

Vous devez ajouter une assertion de type .(string) . C'est nécessaire car la carte est de type map[string]interface{}:

host := arguments["<host>"].(string) + ":" + arguments["<port>"].(string)

La dernière version de Docopt renvoie l' objet Opts qui a des méthodes de conversion:

host, err := arguments.String("<host>")
port, err := arguments.String("<port>")
host_port := host + ":" + port
Grzegorz Żur
la source
7
Je voudrais ajouter que cela s'appelle Assertion de type - golang.org/ref/spec#Type_assertions . Une fois, j'ai eu du mal à comprendre cette terminologie exacte.
Sreejith Ramakrishnan
Cela provoquera une panique si les arguments ["<host>"] sont nuls
Savash
89

Vous n'avez pas besoin d'utiliser une assertion de type, utilisez simplement le %vspécificateur de format avec Sprintf:

hostAndPort := fmt.Sprintf("%v:%v", arguments["<host>"], arguments["<port>"])
Peter Stace
la source
C'était la seule chose que je pouvais faire fonctionner pour moi en essayant de taper l'interface de cast {} avec des chaînes.
FilBot3
1
Pour moi, cela n'a pas fonctionné. Cela a fini par imprimer les graphiques octets ASCII au lieu de la chaîne, comme 201 devient "[50,48,49]", donc j'ai fini par utiliser fmt.Sprintf ("% s", theThing) à la place ...
Felipe Valdes
18

Pour développer ce que Peter a dit: Puisque vous cherchez à passer de l'interface {} à la chaîne, l'assertion de type entraînera des maux de tête puisque vous devez tenir compte de plusieurs types entrants. Vous devrez affirmer chaque type possible et vérifier qu'il s'agit de ce type avant de l'utiliser.

L'utilisation de fmt.Sprintf ( https://golang.org/pkg/fmt/#Sprintf ) gère automatiquement la conversion d'interface. Puisque vous savez que le type de sortie souhaité est toujours une chaîne, Sprintf gérera tout type derrière l'interface sans un tas de code supplémentaire en votre nom.

justitan
la source