Golang中如何在一个模板内渲染两个对象

Golang中如何在一个模板内渲染两个对象 假设我有两个来自数据库的结果集,已成功添加到数组中:resAresB
我想通过执行以下代码在一个模板中渲染它们:
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

5 回复

关于结构体、切片、结构体切片以及切片指针的概念仍然存在混淆。我认为你需要退后几步,重新学习基础知识,确保理解相关类型。这样模板相关的内容就会变得清晰明了。

更多关于Golang中如何在一个模板内渲染两个对象的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


给你的模板提供一个包含其他内容的顶级对象,例如使用映射:

tmpl1.ExecuteTemplate(w, "Index", map[string]interface{}{
  "resA": resA,
  "resB": resB,
})

这可以采用更严格的类型定义,也可以使用结构体来实现。

感谢 @calmh,我有一段如下代码,尝试为模板提供一个包含其他内容的顶级对象。在我的案例中,我想将 resresm 数组同时传递给 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>

这样你就可以在模板中分别访问ResAResB,保持你期望的模板语法不变。

回到顶部