Как преобразовать интерфейс {} в строку?

114

Я использую docopt для анализа аргументов командной строки. Это работает, и в результате получается карта, например

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

Теперь я хотел бы объединить hostи portзначение в строку с двоеточием между двумя значениями. В основном, что-то вроде:

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

К сожалению, это не работает, так как я получаю сообщение об ошибке:

недопустимая операция: arguments [""] + ":" (несовпадающие типы интерфейса {} и строки)

Поэтому, очевидно, мне нужно преобразовать значение, которое я получаю от карты (а это просто interface{}, так что это может быть что угодно) в строку. Теперь мой вопрос: как мне это сделать?

Голо Роден
источник

Ответы:

153

Вам нужно добавить утверждение типа .(string) . Это необходимо, потому что карта имеет тип map[string]interface{}:

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

Последняя версия Docopt возвращает объект Opts , у которого есть методы для преобразования:

host, err := arguments.String("<host>")
port, err := arguments.String("<port>")
host_port := host + ":" + port
Гжегож Дюр
источник
7
Хотел бы добавить, что это называется Утверждение типа - golang.org/ref/spec#Type_assertions . Однажды мне было сложно понять эту точную терминологию.
Сриджит Рамакришнан 02
Если аргументы ["<host>"]
равны
89

Вам не нужно использовать утверждение типа, вместо этого просто используйте %vспецификатор формата с Sprintf:

hostAndPort := fmt.Sprintf("%v:%v", arguments["<host>"], arguments["<port>"])
Питер Стэйс
источник
Это было единственное, что я мог заставить работать для меня, когда пытался ввести приведенный интерфейс {} как строки.
FilBot3
1
Для меня это не сработало. Это закончилось тем, что вместо строки напечатали байтовые диаграммы ASCII, например, 201 стало "[50,48,49]", поэтому я закончил тем, что вместо этого использовал fmt.Sprintf ("% s", theThing) ...
Фелипе Вальдес
18

Чтобы расширить то, что сказал Питер: поскольку вы хотите перейти от интерфейса {} к строке, утверждение типа приведет к головной боли, поскольку вам нужно учитывать несколько входящих типов. Вам нужно будет подтвердить каждый возможный тип и убедиться, что он именно тот тип, прежде чем использовать его.

Использование fmt.Sprintf ( https://golang.org/pkg/fmt/#Sprintf ) автоматически обрабатывает преобразование интерфейса. Поскольку вы знаете, что желаемый тип вывода всегда является строкой, Sprintf обработает любой тип, стоящий за интерфейсом, без кучи дополнительного кода от вашего имени.

Юститан
источник