我正在使用 docopt 来解析命令行参数。这行得通,它会产生一张地图,例如
map[<host>:www.google.de <port>:80 --help:false --version:false]
现在我想将 host
和 port
值连接到一个字符串,两个值之间有一个冒号。基本上,例如:
host := arguments["<host>"] + ":" + arguments["<port>"]
不幸的是,这不起作用,因为我收到错误消息:
无效操作:arguments[""] + ":" (不匹配的类型接口 {} 和字符串)
所以很明显,我需要将从地图中获得的值(只是 interface{}
,所以它可以是任何东西)转换为字符串。现在我的问题是,我该怎么做?
fmt.Sprint(data)
// 其中数据是接口{}
您需要添加 type assertion .(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
您不需要使用类型断言,只需将 %v
格式说明符与 Sprintf
一起使用:
hostAndPort := fmt.Sprintf("%v:%v", arguments["<host>"], arguments["<port>"])
扩展彼得所说的内容:由于您希望从 interface{} 转到字符串,类型断言将导致头疼,因为您需要考虑多种传入类型。您必须声明每种可能的类型并在使用它之前验证它是该类型。
使用 fmt.Sprintf (https://golang.org/pkg/fmt/#Sprintf) 会自动处理接口转换。由于您知道所需的输出类型始终是字符串,因此 Sprintf 将处理接口后面的任何类型,而无需代表您使用一堆额外的代码。
您也可以使用 text/template
:
package main
import (
"text/template"
"strings"
)
func format(s string, v interface{}) string {
t, b := new(template.Template), new(strings.Builder)
template.Must(t.Parse(s)).Execute(b, v)
return b.String()
}
func main() {
m := map[string]interface{}{"<host>": "www.google.de", "<port>": "80"}
s := format(`{{index . "<host>"}}:{{index . "<port>"}}`, m)
println(s == "www.google.de:80")
}
https://pkg.go.dev/text/template