比较 Go 模板中的两个变量
Compare two variables inside Go template
在我传递给模板的数据中,我有两个变量 Type
和 Res.Type
我想与 select 之前的选项进行比较 select 字段.
为了说明我的问题,我创建了这个简化版本:
package main
import (
"bufio"
"bytes"
"html/template"
"log"
)
type Result struct{ Type string }
func main() {
types := map[string]string{
"FindAllString": "FindAllString",
"FindString": "FindString",
"FindStringSubmatch": "FindStringSubmatch",
}
res := &Result{Type: "findAllString"}
templateString := `
<select name="type">
{{ range $key,$value := .Types }}
{{ if eq $key .Res.Type }}
<option value="{{$key}}" selected>{{$value}}</option>
{{ else }}
<option value="{{$key}}">{{$value}}</option>
{{ end }}
{{ end }}
</select>`
t, err := template.New("index").Parse(templateString)
if err != nil {
panic(err)
}
var b bytes.Buffer
writer := bufio.NewWriter(&b)
err = t.Execute(writer, struct {
Types map[string]string
Res *Result
}{types, res})
if err != nil {
panic(err)
}
writer.Flush()
log.Println(b.String())
}
它应该 select "FindAllString"
选项但它只会生成错误
panic: template: index:4:21: executing "index" at <.Res.Type>: can't evaluate field Res in type string
goroutine 1 [running]:
panic(0x53f6e0, 0xc4200144c0)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.main()
/home/tobias/ngo/src/github.com/gamingcoder/tmp/main.go:41 +0x523
exit status 2
当我只是比较两个普通字符串时它起作用了,但我想知道是否有一种惯用的方法可以做到这一点。我看到您可以向模板添加一个函数,但我觉得必须有更简单的方法。
问题是 {{range}}
操作会更改(设置)点 (.
),即使您在案件。在 {{range}}
中,点设置为当前元素。
在{{range}}
里面你写:
{{ if eq $key .Res.Type }}
由于循环中的值是 string
值,.Res.Type
是一个错误,因为没有 Res
字段或 string
值的方法(当前用点 .
).
表示的元素
使用$
符号不引用循环值,而是引用传递给模板执行的参数:
{{ if eq $key $.Res.Type }}
这会工作,但不会给你想要的输出,因为你有一个错字:
res := &Result{Type: "findAllString"}
在 Result
中使用大写字母,因为您的 types
地图还包含大写字母的值:
res := &Result{Type: "FindAllString"}
有了这个你就可以得到想要的输出(在 Go Playground 上试试):
2009/11/10 23:00:00
<select name="type">
<option value="FindAllString" selected>FindAllString</option>
<option value="FindString">FindString</option>
<option value="FindStringSubmatch">FindStringSubmatch</option>
</select>
另请注意,您可以像这样简单地编写循环:
{{range $key, $value := .Types}}
<option value="{{$key}}"{{if eq $key $.Res.Type}} selected{{end}}>{{.}}</option>
{{end}}
另请注意,出于测试目的,您可以简单地将 os.Stdout
作为编写器传递给模板执行,您将在控制台上看到结果,而无需创建和使用缓冲区,例如:
err = t.Execute(os.Stdout, struct {
Types map[string]string
Res *Result
}{types, res})
在 Go Playground 上试试简化版。
阅读此答案以获得更多见解:
在我传递给模板的数据中,我有两个变量 Type
和 Res.Type
我想与 select 之前的选项进行比较 select 字段.
为了说明我的问题,我创建了这个简化版本:
package main
import (
"bufio"
"bytes"
"html/template"
"log"
)
type Result struct{ Type string }
func main() {
types := map[string]string{
"FindAllString": "FindAllString",
"FindString": "FindString",
"FindStringSubmatch": "FindStringSubmatch",
}
res := &Result{Type: "findAllString"}
templateString := `
<select name="type">
{{ range $key,$value := .Types }}
{{ if eq $key .Res.Type }}
<option value="{{$key}}" selected>{{$value}}</option>
{{ else }}
<option value="{{$key}}">{{$value}}</option>
{{ end }}
{{ end }}
</select>`
t, err := template.New("index").Parse(templateString)
if err != nil {
panic(err)
}
var b bytes.Buffer
writer := bufio.NewWriter(&b)
err = t.Execute(writer, struct {
Types map[string]string
Res *Result
}{types, res})
if err != nil {
panic(err)
}
writer.Flush()
log.Println(b.String())
}
它应该 select "FindAllString"
选项但它只会生成错误
panic: template: index:4:21: executing "index" at <.Res.Type>: can't evaluate field Res in type string
goroutine 1 [running]:
panic(0x53f6e0, 0xc4200144c0)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.main()
/home/tobias/ngo/src/github.com/gamingcoder/tmp/main.go:41 +0x523
exit status 2
当我只是比较两个普通字符串时它起作用了,但我想知道是否有一种惯用的方法可以做到这一点。我看到您可以向模板添加一个函数,但我觉得必须有更简单的方法。
问题是 {{range}}
操作会更改(设置)点 (.
),即使您在案件。在 {{range}}
中,点设置为当前元素。
在{{range}}
里面你写:
{{ if eq $key .Res.Type }}
由于循环中的值是 string
值,.Res.Type
是一个错误,因为没有 Res
字段或 string
值的方法(当前用点 .
).
使用$
符号不引用循环值,而是引用传递给模板执行的参数:
{{ if eq $key $.Res.Type }}
这会工作,但不会给你想要的输出,因为你有一个错字:
res := &Result{Type: "findAllString"}
在 Result
中使用大写字母,因为您的 types
地图还包含大写字母的值:
res := &Result{Type: "FindAllString"}
有了这个你就可以得到想要的输出(在 Go Playground 上试试):
2009/11/10 23:00:00
<select name="type">
<option value="FindAllString" selected>FindAllString</option>
<option value="FindString">FindString</option>
<option value="FindStringSubmatch">FindStringSubmatch</option>
</select>
另请注意,您可以像这样简单地编写循环:
{{range $key, $value := .Types}}
<option value="{{$key}}"{{if eq $key $.Res.Type}} selected{{end}}>{{.}}</option>
{{end}}
另请注意,出于测试目的,您可以简单地将 os.Stdout
作为编写器传递给模板执行,您将在控制台上看到结果,而无需创建和使用缓冲区,例如:
err = t.Execute(os.Stdout, struct {
Types map[string]string
Res *Result
}{types, res})
在 Go Playground 上试试简化版。
阅读此答案以获得更多见解: