Go语言 如何呈现一个“模板的模板”,而不逃避每个动作

slwdgvem  于 2023-05-11  发布在  Go
关注(0)|答案(3)|浏览(137)

有没有人知道如何用text/template渲染一个“模板的模板”,其中只有特定的动作(即: Package 在{{...}}中的东西)将被呈现,其余的将被视为文字?
例如,给定以下模板:

I want to render {{.Foo}}.

but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}

Render {{.Foo}} again.

我想呈现以下输出:

I want to render foo.

but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}

Render foo again.

虽然我可以用{{ "{{" }}转义我想要的文字的每一部分,但感觉有点乏味。
我想我应该能够做一些类似I want to render {{template "outer" .Foo}}.的事情,并调用一些类似tmpl.ExecuteTemplate(&buff, "outer", data)的东西来只呈现我指定的“外部”操作。
我还想知道渲染“模板的模板”是否是一种代码气味,如果可能的话,我应该用字符串/replace替换我的“外部”模板,比如I want to render <<.Foo>>

bmvo0sr5

bmvo0sr51#

您可以更改第一级模板的分隔符:

tmpl := template.New("name").Delims("<<",">>").Parse(...)

然后,将模板编写为:

I want to render <<.Foo>>.

but I don't want to render anything on this line, like {{.Bar}}...
vmpqdwk3

vmpqdwk32#

{{define "outer"}}
I want to render {{.}}
{{end}}

{{$ignored := `but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}`}}

{{template "outer" .Foo}}

{{$ignored}}

Render {{template "outer" .Foo}} again.
afdcj2ne

afdcj2ne3#

选项1:内部模板和外部模板使用不同的分隔符。

t := template.Must(template.New("").Delims("<<", ">>").Parse(`
I want to render <<.Foo>>.

but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}

Render <<.Foo>> again.`))

本方案:

var buf bytes.Buffer
if err := t.Execute(&buf, map[string]any{"Foo": "foo"}); err != nil {
    log.Fatal(err)
}
fmt.Println(buf.String())

打印:

I want to render foo.

but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}

Render foo again.

https://go.dev/play/p/ueqstNKVUWQ

**选项2:**将整行作为字符串文字输出。这要求行中的"被引用,但这并不像引用所有{{那么糟糕。

I want to render {{.Foo}}.

{{"but I don't want to render anything on this line, like {{.Bar}} or this template: [{{ .Status | toUpper }}{{ if eq .Status \"firing\" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }} for {{ .CommonLabels.job }}"}}

Render {{.Foo}} again.

https://go.dev/play/p/ueqstNKVUWQ

相关问题