Go Template get a variable dynamically

huangapple go评论83阅读模式
英文:

Go Template get a variable dynamically

问题

我有一个看起来像这样的yml参数:

nodes: one, two
instanceMinOne: 1
instanceMaxOne: 2
instanceMinTwo: 4
instanceMaxTwo: 6

有没有办法使用go模板动态读取例如instanceMinOne,其中变量名由instanceMin + 来自节点列表的动态值组成?

类似于(这显然不起作用,只是给出我想要实现的想法):

{{- range $nodeName := (split .Parameters.nodes) }}
   instance-min: {{ .Parameters.instanceMin$nodeName }}
   instance-max: {{ .Parameters.instanceMan$nodeName }}
{{- end }}
英文:

I have yml parameters that look like

nodes: one, two
instanceMinOne: 1
instanceMaxOne: 2
instanceMinTwo: 4
instanceMaxTwo: 6

Is there a way with go templating to dynamically read for example instanceMinOne where the variable name is composed of instanceMin + the dynamic value coming from the nodes list ?

something like (this obviously doesn't work but just give the idea of what I'd like to achieve)

{{ - range $nodeName := (split .Parameters.nodes) } } } }
   instance-min: {{ .Parameters.instanceMin$nodeName }}
   instance-max: {{ .Parameters.instanceMan$nodeName }}
{{ - end }}

答案1

得分: 3

要实现你想要的结果,你需要解决两个任务:

  • 字符串拼接
  • 使用动态值进行索引

对于字符串拼接,你可以使用内置的 print 函数,例如:

{{ $key := print "instanceMin" $nodeName }}

对于索引,使用内置的 index 函数:

instance-min: {{ index $.Parameters $key }}

(注意:{{range}} 动作会改变当前的上下文,所以在其中需要使用 $ 来引用循环外的变量。)

或者可以写成一行:

instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}

以下是一个可运行的示例:

func main() {
	t := template.Must(template.New("").Parse(src))

	params := map[string]interface{}{
		"Parameters": map[string]interface{}{
			"nodes":          []string{"One", "Two"},
			"instanceMinOne": 1,
			"instanceMaxOne": 2,
			"instanceMinTwo": 4,
			"instanceMaxTwo": 6,
		},
	}

	if err := t.Execute(os.Stdout, params); err != nil {
		panic(err)
	}
}

const src = `{{- range $idx, $nodeName := .Parameters.nodes }}
   instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}
   instance-max: {{ index $.Parameters (print "instanceMax" $nodeName) }}
{{- end }}`

运行结果如下(可以在 Go Playground 上尝试):

instance-min: 1
instance-max: 2
instance-min: 4
instance-max: 6
英文:

To achieve what you want, you have to solve 2 tasks:

  • string concatenation
  • indexing with a dynamic value

For concatenation you may use the builtin print function, e.g.

{{ $key := print "instanceMin" $nodeName }}

For indexing, use the builtin index function:

instance-min: {{ index $.Parameters $key }}

(Note: The {{range}} action changes the dot, so inside it you need $ to reference outside of the loop variable.)

Or in one line:

instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}

See a runnable demo:

func main() {
	t := template.Must(template.New("").Parse(src))

	params := map[string]any{
		"Parameters": map[string]any{
			"nodes":          []string{"One", "Two"},
			"instanceMinOne": 1,
			"instanceMaxOne": 2,
			"instanceMinTwo": 4,
			"instanceMaxTwo": 6,
		},
	}

	if err := t.Execute(os.Stdout, params); err != nil {
		panic(err)
	}
}

const src = `{{- range $idx, $nodeName := .Parameters.nodes }}
   instance-min: {{ index $.Parameters (print "instanceMin" $nodeName) }}
   instance-max: {{ index $.Parameters (print "instanceMax" $nodeName) }}
{{- end }}`

This will output (try it on the Go Playground):

instance-min: 1
instance-max: 2
instance-min: 4
instance-max: 6

huangapple
  • 本文由 发表于 2023年7月4日 15:58:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76610476.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定