英文:
How to pass multiple data to Go template?
问题
我想将两个数据对象传递给Go模板。一个是MongoDB查询结果,另一个是整数数组。
MongoDB查询代码如下:
var results []User
sess, db := GetDatabase()
defer sess.Close()
c := db.C("user")
err := c.Find(nil).All(&results)
我想通过以下代码传递'results'和一个整数数组:
GetTemplate("list").Execute(w, ???????)
如果只有数据库查询结果,我们可以这样使用:
GetTemplate("list").Execute(w, results)
在模板中,我们可以通过{{.Name}}等方式访问它(其中Name是[]User的结构字段)。
请告诉我如何传递这些数据,并在模板中如何访问它们。
英文:
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, db := GetDatabase()
defer sess.Close()
c := db.C("user")
err := c.Find(nil).All(&results)
I want to sent 'result' and an int array through following code
GetTemplate("list").Execute(w,???????)
If there is only db result, we could use it as
GetTemplate("list").Execute(w,results)
and in template we could access it {{.Name}} etc. (where Name is a struct field of []User)
Please tell me how to pass these data and how to access them in template.
答案1
得分: 26
您只能传递一个值,但该值可以是多个值的组合,例如结构体、映射或切片。因此,只需将模板中的多个数据包装在struct
或map
中。
使用struct
的示例:
type Data struct {
Results []User // 必须是导出的!
Other []int // 必须是导出的!
}
data := &Data{results, []int{1, 2, 3}}
if err := GetTemplate("list").Execute(w, data); err != nil {
// 处理错误
}
还要注意,不需要新的命名类型,您也可以使用匿名结构体字面量,如下所示:
data := struct {
Results []User // 必须是导出的!
Other []int // 必须是导出的!
}{results, []int{1, 2, 3}}
使用map
的示例:
m := map[string]interface{}{
"Results": results,
"Other": []int{1, 2, 3},
}
if err := GetTemplate("list").Execute(w, m); err != nil {
// 处理错误
}
请注意,使用映射时,不需要使用大写的字符串作为键,例如您也可以使用"results"
和"other"
(但我认为最好使用以大写字母开头的键,这样如果将来转换为struct
,您需要进行的更正就会更少)。
在这两种情况下,您可以使用{{.Results}}
引用[]User
结果,使用{{.Other}}
引用附加的整数切片。
因此,例如要遍历用户:
{{range .Results}}
用户名:{{.Name}}
{{end}}
使用slice
的示例:
s := []interface{}{
results,
[]int{1, 2, 3},
}
if err := GetTemplate("list").Execute(w, s); err != nil {
// 处理错误
}
这种方法不太易读,但是是可行的解决方案。在模板中,您必须对模板数据进行索引以获取“单个”值,例如:
{{range index . 0}}
用户名:{{.Name}}
{{end}}
其他:{{index . 1}}
在Go Playground上尝试一下。
其他方法...
还有其他“理论上”的方法,但我不会使用它们仅仅因为它们能工作。
例如,您还可以传递一个通道,从中接收值。
另一种解决方案可能是注册自定义函数,当调用时会返回这些值。
英文:
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 string
s 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.
答案2
得分: 1
你应该定义一个包含数据库查询结果的结构体,然后将该结构体赋值给Execute
方法。
tmpl.Execute
需要一个Writer
接口和一个struct
。
type Inventory struct {
Material string
Count uint
}
items := Inventory{"裤子", 1}
if err := GetTemplate("list").Execute(w, items); err != nil {
// ... 做你的工作
}
英文:
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
}
答案3
得分: 0
你可以使用range
关键字将结构体放在另一个结构体中。例如:
type Data struct {
Users []User
Developers []Developer
}
var data = Data{
Users: ...,
Developers: ...,
}
err := t.Execute(w, &data)
if err != nil {
panic(err)
}
{{range .Users}}{{.UserName}}
{{end}}
{{range .Developers}}{{.DeveloperName}}
{{end}}
请注意,这是一个示例代码片段,其中User
和Developer
是自定义的结构体类型。你需要根据实际情况进行适当的替换。
英文:
You can put your structs inside another struct using the range
keyword. e.g
type Data struct {
Users []User
Developers []Developer
}
var data = Data{
Users: ...,
Developers: ...,
}
err := t.Execute(w, &data)
if err != nil {
panic(err)
}
{{range .Users}}{{.UserName}}
{{end}}
{{range .Developers}}{{.DeveloperName}}
{{end}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论