Golang中如何在一个模板内渲染两个对象
Golang中如何在一个模板内渲染两个对象
假设我有两个来自数据库的结果集,已成功添加到数组中:resA 和 resB
我想通过执行以下代码在一个模板中渲染它们:
tmpl1.ExecuteTemplate(w, "Index", resA, resB) 但我知道这会失败。
在 Go 模板中,这类需求是如何实现的?
在我的模板中,我希望像这样访问它们:
{{range .ResA}} resA field-1 is: {{.resA-f1}} resA field-2 is {{.resA-f2}} {{end}} {{range .ResB}} resB field-1 is: {{.resB-f1}} resB field-2 is {{.resB-f2}} {{end}}
更多关于Golang中如何在一个模板内渲染两个对象的实战教程也可以访问 https://www.itying.com/category-94-b0.html
关于结构体、切片、结构体切片以及切片指针的概念仍然存在混淆。我认为你需要退后几步,重新学习基础知识,确保理解相关类型。这样模板相关的内容就会变得清晰明了。
更多关于Golang中如何在一个模板内渲染两个对象的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
给你的模板提供一个包含其他内容的顶级对象,例如使用映射:
tmpl1.ExecuteTemplate(w, "Index", map[string]interface{}{
"resA": resA,
"resB": resB,
})
这可以采用更严格的类型定义,也可以使用结构体来实现。
感谢 @calmh,我有一段如下代码,尝试为模板提供一个包含其他内容的顶级对象。在我的案例中,我想将 res 和 resm 数组同时传递给 Data 结构体。
我知道我遗漏了某些内容并遇到了错误:
# command-line-arguments
./main.go:132:36: cannot use &res (type *[]Year) as type *Year in array or slice literal
./main.go:133:37: cannot use &resm (type *[]Month) as type *Month in array or slice literal
请问我现在的做法正确吗?是否有更好的实现方式? 提前感谢您的帮助。
type Month struct {
Mname string
Color string
Id int
}
type Year struct {
Yname, Color string
Selected bool
}
type Data struct {
Years []*Year
Months []*Month
}
var tmpl3 = template.Must(template.ParseGlob("report/*"))
func ShowMonth(w http.ResponseWriter, r *http.Request) {
db := dbConn()
///////////////////////////////////////////////////////////////////////////
if r.Method == "POST" {
years := r.FormValue("years")
selDB, err := db.Query("SELECT MONTHNAME(Rdate) as months, color, report_monthly_id as id FROM report_monthly WHERE YEAR(Rdate)=?", years )
if err != nil {
panic(err.Error())
}
resm := []Month{}
for selDB.Next() {
var months, color string
var id int
err = selDB.Scan(&months, &color, &id)
if err != nil {
panic(err.Error())
}
rep := Month{Mname: months, Color: color, Id: id}
resm = append(resm, rep)
}
///////////////////////////////////////////////////////////////////////////
selDB1, err := db.Query("SELECT DISTINCT YEAR(Rdate) as years, color FROM report_monthly ORDER BY report_monthly_id DESC")
if err != nil {
panic(err.Error())
}
res := []Year{}
for selDB1.Next() {
var years, color string
err = selDB1.Scan(&years, &color)
if err != nil {
panic(err.Error())
}
rep := Year{Yname: years, Color: color}
res = append(res, rep)
}
// f2 := Month{Mname: "FEB", Color: "BLUE"}
// f3 := Year{Yname: "2018", Selected: false}
person := Data{Years: []*Year{&res},
Months: []*Month{&resm}}
// log.Println(resm)
log.Println(person)
tmpl3.ExecuteTemplate(w, "IndexReport", person)
defer db.Close()
}
}
在Go模板中,ExecuteTemplate方法只能接受单个数据参数。要在一个模板中渲染多个对象,你需要将它们封装到一个结构体或map中。
以下是实现方法:
方法1:使用结构体封装
type TemplateData struct {
ResA []YourTypeA
ResB []YourTypeB
}
// 准备数据
data := TemplateData{
ResA: resA,
ResB: resB,
}
// 执行模板
tmpl1.ExecuteTemplate(w, "Index", data)
方法2:使用map封装
data := map[string]interface{}{
"ResA": resA,
"ResB": resB,
}
tmpl1.ExecuteTemplate(w, "Index", data)
完整示例
package main
import (
"html/template"
"net/http"
)
type User struct {
Name string
Age int
}
type Product struct {
Name string
Price float64
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// 模拟数据
users := []User{
{"Alice", 25},
{"Bob", 30},
}
products := []Product{
{"Laptop", 999.99},
{"Mouse", 29.99},
}
// 使用map封装数据
data := map[string]interface{}{
"Users": users,
"Products": products,
}
tmpl := template.Must(template.ParseFiles("template.html"))
tmpl.Execute(w, data)
})
http.ListenAndServe(":8080", nil)
}
对应的模板文件 template.html:
<!DOCTYPE html>
<html>
<body>
<h2>Users:</h2>
{{range .Users}}
<p>Name: {{.Name}}, Age: {{.Age}}</p>
{{end}}
<h2>Products:</h2>
{{range .Products}}
<p>Product: {{.Name}}, Price: ${{.Price}}</p>
{{end}}
</body>
</html>
这样你就可以在模板中分别访问ResA和ResB,保持你期望的模板语法不变。

