Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Go HTML模板中创建结构映射键的语法_Go_Go Templates - Fatal编程技术网

在Go HTML模板中创建结构映射键的语法

在Go HTML模板中创建结构映射键的语法,go,go-templates,Go,Go Templates,我正在编写一个简单的Go程序来显示每个环境中部署的服务版本的HTML表。我的程序包含以下结构: type versionKey struct { Environment string Service string } type templateData struct { Environments []string Services []string Versions map[versionKey]string } 如您所见,Ve

我正在编写一个简单的Go程序来显示每个环境中部署的服务版本的HTML表。我的程序包含以下结构:

type versionKey struct {
    Environment string
    Service     string
}

type templateData struct {
    Environments []string
    Services     []string
    Versions     map[versionKey]string
}
如您所见,
Versions
映射使用
versionKey
作为字符串值的键,例如
“1.0.0”

我将
templateData
struct传递给一个HTML模板,并在其
环境
服务
切片上进行排列,以构建HTML表。问题是,我需要为环境和服务的任何给定交叉点构造一个
versionKey
,以便使用它从
Versions
映射中查找版本,并在表格单元格中输出该值

在模板中,我有
$environment
$service
变量可供选择,但我无法计算Go模板语法来创建
versionKey
结构

以下是省略标记的模板代码:

{{$environments := .Environments}}
{{$services := .Services}}
{{$versions := .Versions}}

{{range $service := $services}}
  ...
  {{range $environment := $environments}}
    ...
    {{index $versions ...? }} // How to create versionKey struct map key here?
    ...
  {{end}}
  ...
{{end}}

仅使用模板代码,您不能。要做到这一点,您需要执行Go代码提供某种支持。根据设计理念,模板不应包含复杂的逻辑。您可能会争论这是否复杂,但模板语法不支持这一点

最简单的解决方案是将
Version()
方法添加到
templateData
结构中,该结构将简单地返回给定环境和服务的版本:

func (t *templateData) Version(environment, service string) string {
    return t.Versions[versionKey{
        Environment: environment,
        Service:     service,
    }]
}
从模板中使用此选项:

{{range $service := $services -}}
  {{range $environment := $environments}}
    {{$environment}} - {{$service}} version: {{$.Version $environment $service}}
  {{end}}
{{end}}
测试它:

t := template.Must(template.New("").Parse(templ))
td := &templateData{
    Environments: []string{"EnvA", "EnvB"},
    Services:     []string{"ServA", "ServB"},
    Versions: map[versionKey]string{
        {"EnvA", "ServA"}: "1.0.0",
        {"EnvA", "ServB"}: "1.0.1",
        {"EnvB", "ServA"}: "1.0.2",
    },
}
if err := t.Execute(os.Stdout, td); err != nil {
    panic(err)
}
输出(在上尝试):

选择 代替
templateData.Version()
方法,您可以轻松注册一个函数,该函数可以从给定的环境和服务创建并返回
versionKey
类型的值。有关详细信息,请参阅。这将更复杂,但更灵活,因为它可以在其他地方重用。请参见此处的示例:。这种方法的一个微小变化是将函数值作为任何其他模板数据传递,而不是将其注册为可调用的命名函数

另一种选择是将
版本
字段“转换”为地图地图,例如:

Versions map[string]map[string]string

首先可以按环境索引,然后按服务索引,在模板中可以通过2个
{{index}}
操作来实现。不过,您必须检查第一次索引是否会产生任何结果。

这是一个极好的答案,非常感谢。出于兴趣,为什么要为
templateData
使用指针?@JohnTopley(指针和非指针接收器)在这个简单的示例中都可以使用。我使用指针接收器完全是出于习惯,如果这个例子演变成一个更复杂的例子,其中方法也需要改变/修改接收器,我不必返回并将接收器更改为指针接收器。
Versions map[string]map[string]string