在使用Golang的模板引擎时,我们经常需要自定义函数来处理一些特定的逻辑。然而,当我们将自定义函数与html/template包中的FuncMap结合使用时,可能会遇到一种奇怪的问题:产生空响应。php小编香蕉将在本文中介绍这个问题的原因,并提供解决方案,以确保我们能够正确地使用Golang模板引擎。
问题内容
使用 html/template 我试图使用 template.FuncMap
从 time.Time
类型的字段填充 HTML 表单中的日期字段,但它对我不起作用。
以下代码有效,
type Task struct {
ID int
ProjectID int
Description string
StartDate time.Time
Duration float32
}
type ProjectTaskData struct {
ProjectID int
ProjectName string
TaskDetails Task
FormattedStartDate string // this field is a hack/workaround for me
}
登录后复制
我修剪后的 main
函数,
func main() {
db := GetConnection()
r := mux.NewRouter()
// other handlers here are removed
r.HandleFunc("/project/{project-id}/add-task", AddTask(db))
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
http.ListenAndServe(":8080", r)
}
登录后复制
AddTask
函数,
func AddTask(db *sql.DB) func(w http.ResponseWriter, r *http.Request) {
//tmpl := template.Must(template.New("").Funcs(template.FuncMap{
// "startdate": func(t time.Time) string { return t.Format("2006-01-02") },
//}).ParseFiles("static/add_task.html"))
tmpl := template.Must(template.ParseFiles("static/add_task.html"))
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
projectID, err := strconv.Atoi(vars["project-id"])
if err != nil {
log.Fatal(err)
}
var projectName string
var projectStartDate time.Time
err = db.QueryRow(`select name, start_date from projects where id = ?`, projectID).Scan(&projectName, &projectStartDate)
switch {
case err == sql.ErrNoRows:
log.Printf("No project with id %dn", projectID)
return
case err != nil:
log.Fatalf("Query error: %vn", err)
default:
log.Printf("Got project %v with id %dn", projectName, projectID)
}
if r.Method != http.MethodPost {
data := ProjectTaskData{
ProjectID: projectID,
ProjectName: projectName,
TaskDetails: Task{
ProjectID: projectID,
Description: "",
StartDate: projectStartDate,
Duration: 1,
},
FormattedStartDate: projectStartDate.Format(time.DateOnly),
}
tmpl.Execute(w, data)
return
}
// rest of code handling the post action here
http.Redirect(w, r, "/project/"+fmt.Sprint(projectID)+"/tasks", http.StatusFound)
}
}
登录后复制
在 add_task.html
中,如果我放置以下占位符,则当我点击 http://localhost:8080/project/1/add-task 时,它能够填充开始日期,
登录后复制
但是,如果我替换 AddTask() 中的以下第一行,
tmpl := template.Must(template.ParseFiles("static/add_task.html"))
登录后复制
与下面的一个,
tmpl := template.Must(template.New("").Funcs(template.FuncMap{
"startdate": func(t time.Time) string { return t.Format("2006-01-02") },
}).ParseFiles("static/add_task.html"))
登录后复制
如果我按如下方式更改 add_task.html,
登录后复制
当我点击 http://localhost:8080/project/1/add-task 时,我得到一个空响应(但我得到 200 OK)
我还提到了以下问题,但没有成功,
https://stackoverflow.com/a/35550730/8813473
解决方法
正如 @icza 在评论中提到的,从 Template.Execute()
收到错误揭示了这个问题。
我收到错误,
template: "" 是一个不完整或空的模板
参考https://www.php.cn/link/949686ecef4ee20a62d16b4a2d7ccca3的答案,我更改了template .New("")
调用 template.New("add_task.html")
来解决该问题。
最终代码如下所示,
tmpl := template.Must(template.New("add_task.html").Funcs(template.FuncMap{
"startdate": func(t time.Time) string { return t.Format("2006-01-02") },
}).ParseFiles("static/add_task.html"))
登录后复制
以上就是Golang 模板:将 FuncMap 与 html/template 结合使用会产生空响应的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!