Golang模板学习过程中遇到的问题

Golang模板学习过程中遇到的问题 我是Go语言的新手,但很享受学习过程。下面的代码生成了一个HTML表格的主体部分:

{{define "table"}}
[table class="w3-table w3-striped"]
[thead]
[tr class="w3-yellow"]
[th]Created[/th]
[th>Todo[/th]
[th>Reminder[/th]
[/tr]
[/thead]
[tbody]
{{with .}} {{range .}}
[tr onclick="console.log('row clicked')"]
[td]{{.Datecreated}}[/td]
[td]{{.Todo}}[/td]
[td]{{.Datereminder}}[/td]
[td style="display: none"]{{.ID}}[/td]
[/tr]
{{end}} {{end}}
[/tbody]
[/table>
{{end}}

如果我将生成的HTML输出到os.StdOut,表格主体是存在的。我把生成的代码放到一个文件中,在Chrome里运行,显示正常。然而,当我使用Chrome访问localhost:3000时,页面中唯一缺失的部分就是表格主体,它是空的。我使用的是Content-Type: text/html

这让我很困惑,任何帮助都将不胜感激。

抱歉HTML代码的呈现方式有问题,我得再读一遍说明。


更多关于Golang模板学习过程中遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

那么,实际渲染模板并发送响应的代码是什么?

更多关于Golang模板学习过程中遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个典型的Go模板执行问题。问题很可能出在模板执行时传递的数据结构上。让我分析一下你的代码:

// 问题分析:
// 1. 你的模板使用了 {{with .}} {{range .}} 这意味着期望传入一个可迭代的数据结构
// 2. 如果表格主体为空,很可能是传入的数据为nil或空切片

// 正确的模板使用示例:
package main

import (
    "html/template"
    "net/http"
    "os"
)

type TodoItem struct {
    ID           int
    Datecreated  string
    Todo         string
    Datereminder string
}

func main() {
    // 示例1:直接输出到stdout(你的测试方式)
    tmpl := template.Must(template.New("table").Parse(`{{define "table"}}
<table class="w3-table w3-striped">
<thead>
<tr class="w3-yellow">
<th>Created</th>
<th>Todo</th>
<th>Reminder</th>
</tr>
</thead>
<tbody>
{{with .}}{{range .}}
<tr onclick="console.log('row clicked')">
<td>{{.Datecreated}}</td>
<td>{{.Todo}}</td>
<td>{{.Datereminder}}</td>
<td style="display: none">{{.ID}}</td>
</tr>
{{end}}{{end}}
</tbody>
</table>
{{end}}`))

    // 测试数据
    data := []TodoItem{
        {ID: 1, Datecreated: "2023-01-01", Todo: "学习Go", Datereminder: "2023-12-31"},
        {ID: 2, Datecreated: "2023-01-02", Todo: "学习模板", Datereminder: "2023-12-31"},
    }

    // 输出到stdout - 这会正常工作
    tmpl.ExecuteTemplate(os.Stdout, "table", data)

    // 示例2:HTTP服务器中的常见问题
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        
        // 常见错误1:传递了nil数据
        // tmpl.ExecuteTemplate(w, "table", nil) // 这会导致表格为空
        
        // 常见错误2:传递了错误的数据结构
        // tmpl.ExecuteTemplate(w, "table", TodoItem{}) // 这也会导致表格为空
        
        // 正确的方式:传递切片数据
        tmpl.ExecuteTemplate(w, "table", data)
    })

    http.ListenAndServe(":3000", nil)
}

// 调试建议:在HTTP处理器中添加日志
func handler(w http.ResponseWriter, r *http.Request) {
    // 检查数据
    var todos []TodoItem
    // ... 从数据库或其他来源获取数据
    
    // 添加调试日志
    fmt.Printf("数据长度: %d\n", len(todos))
    if len(todos) == 0 {
        fmt.Println("警告: 数据切片为空")
    }
    
    // 确保Content-Type正确设置
    w.Header().Set("Content-Type", "text/html; charset=utf-8")
    
    // 执行模板
    err := tmpl.ExecuteTemplate(w, "table", todos)
    if err != nil {
        fmt.Printf("模板执行错误: %v\n", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

关键点:

  1. 确保传递给模板的数据是 []TodoItem 类型的切片,而不是单个结构体
  2. 检查数据源是否真的返回了数据
  3. 在HTTP处理器中添加错误处理和日志来调试
  4. 确保Content-Type正确设置为 text/html; charset=utf-8

最常见的错误是数据库查询返回空结果或nil,导致模板中的 {{with .}} 条件不满足。

回到顶部