dongyan3562 2017-06-24 08:34
浏览 31
已采纳

比较Go模板中的两个变量

In the data I pass to my template I have the two variables Type and Res.Type I want to compare to preselect an option for my select field.

To illustrate my problem I have created this simplified version:

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())
}

It should select the "FindAllString" option but it only generates the error

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

When I just compare two normal strings it works but I want to know if there is an idomatic way to do this. I have seen that you could add a function to the template but I feel that there must be a simpler way for this.

  • 写回答

1条回答 默认 最新

  • doutang9037 2017-06-24 08:43
    关注

    The problem is that the {{range}} action changes (sets) the dot (.) even if you use loop variables ($key and $value) in your case. Inside a {{range}} the dot is set to the current element.

    And inside {{range}} you write:

    {{ if eq $key .Res.Type }}
    

    Since values in your loop are string values, .Res.Type is an error, because there is no Res field or method of a string value (the current element denoted by the dot .).

    Use the $ sign to not refer to the loop value, but to the param passed to the template execution:

    {{ if eq $key $.Res.Type }}
    

    This will work, but won't give you the desired output, as you have a typo:

    res := &Result{Type: "findAllString"}
    

    Use capital letter in Result as your types map also contains values with capital letter:

    res := &Result{Type: "FindAllString"}
    

    With this you get the desired output (try it on the 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>
    

    Also note that you could simply write the loop like this:

    {{range $key, $value := .Types}}
        <option value="{{$key}}"{{if eq $key $.Res.Type}} selected{{end}}>{{.}}</option>
    {{end}}
    

    Also note that for testing purposes you may simply pass os.Stdout as the writer for template execution, and you'll see the result on your console without having to create and use a buffer, e.g.:

    err = t.Execute(os.Stdout, struct {
        Types map[string]string
        Res   *Result
    }{types, res})
    

    Try the simplified version on the Go Playground.

    Read this answer for more insights: golang template engine pipelines

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)
  • ¥20 matlab yalmip kkt 双层优化问题
  • ¥15 如何在3D高斯飞溅的渲染的场景中获得一个可控的旋转物体
  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入