How to pass multiple data to Go template?

后端 未结 2 1565
自闭症患者
自闭症患者 2020-11-30 11:35

I want to pass two data objects to Go Template. One is a MongoDB query result and other is an integer array.

MongoDB Query:-

var results []User
sess,         


        
相关标签:
2条回答
  • 2020-11-30 12:04

    You may only pass a single value, but that value may be a composed value of multiple values, e.g. a struct, map or slice. So simply wrap your multiple data intended for the template in a struct or in a map.

    Example with a struct:

    type Data struct {
        Results []User // Must be exported!
        Other   []int  // Must be exported!
    }
    
    data := &Data{results, []int{1, 2, 3}}
    if err := GetTemplate("list").Execute(w, data); err != nil {
        // Handle error
    }
    

    Also note that a new, named type is not required, you could also use an anonymous struct literal, which could look like this:

    data := struct {
        Results []User // Must be exported!
        Other   []int  // Must be exported!
    }{results, []int{1, 2, 3}}
    

    Example with a map:

    m := map[string]interface{}{
        "Results": results,
        "Other":   []int{1, 2, 3},
    }
    
    if err := GetTemplate("list").Execute(w, m); err != nil {
        // Handle error
    }
    

    Note that using a map, it is not required to use capitalized strings as keys, e.g. you could've used "results" and "other" too (but in my opinion it's better to use keys with capital starting letters, should you move to struct sometimes in the future, you would have less corrections to make).

    In both cases you may refer to the []User results with {{.Results}} and to the additional int slice with {{.Other}}.

    So for example to range over the users:

    {{range .Results}}
        User name:{{.Name}}
    {{end}}
    

    Example with a slice:

    s := []interface{}{
        results,
        []int{1, 2, 3},
    }
    
    if err := GetTemplate("list").Execute(w, s); err != nil {
        // Handle error
    }
    

    This is less readable, but a viable solution. In the template you have to index the template data to get the "individual" values, e.g.:

    {{range index . 0}}
        User name:{{.Name}}
    {{end}}
    
    Other: {{index . 1}}
    

    Try it on the Go Playground.

    Other ways...

    There are other "theoretical" ways too, but I wouldn't use them just because it works.

    For example, you could also pass in a channel from which receives would provide the values.

    Yet another solution could be to register custom functions which when called would return the values.

    0 讨论(0)
  • 2020-11-30 12:14

    You should define a struct populated with the database results query, then assign that struct to the Execute method.

    tmpl.Execute require a Writer interface and a struct

    type Inventory struct {
        Material string
        Count    uint
    }
    
    items := Inventory{"trouser", 1}    
    if err := GetTemplate("list").Execute(w, items); err != nil {
        // ... do your work
    }
    
    0 讨论(0)
提交回复
热议问题