在传递给模板的数据中,我有两个变量Type,Res.Type我想进行比较以为select字段预选择一个选项。
Type
Res.Type
为了说明我的问题,我创建了这个简化的版本:
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()) }
它应该选择"FindAllString"选项,但只会产生错误
"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}}操作也会更改(设置)点(.)。在圆点内部设置为当前元素。$key``$value``{{range}}
{{range}}
.
$key``$value``{{range}}
在里面{{range}}写:
{{ if eq $key .Res.Type }}
由于循环中的string值是值,因此.Res.Type是错误的,因为没有值的Res字段或方法string(当前元素由点表示.)。
string
.Res.Type
Res
使用$符号不引用循环值,而是引用传递给模板执行的参数:
$
{{ if eq $key $.Res.Type }}
这会起作用,但不会产生所需的输出,因为您有错字:
res := &Result{Type: "findAllString"}
使用大写字母,Result因为您的types地图还包含带有大写字母的值:
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编写者身份来执行模板,并且无需创建和使用缓冲区即可在控制台上看到结果,例如:
os.Stdout
err = t.Execute(os.Stdout, struct { Types map[string]string Res *Result }{types, res})
在Go Playground上尝试简化版本。