Golang templates: Using FuncMap with html/template produces empty response

王林
Release: 2024-02-12 11:24:07
forward
1086 people have browsed it

Golang 模板:将 FuncMap 与 html/template 结合使用会产生空响应

When using Golang's template engine, we often need custom functions to handle some specific logic. However, when we combine a custom function with the FuncMap in the html/template package, we may encounter a strange problem: an empty response is produced. PHP editor Banana will introduce the cause of this problem in this article and provide solutions to ensure that we can use the Golang template engine correctly.

Question content

Using html/template I am trying to use template.FuncMap to populate a date field in an HTML form from a field of type time.Time , but it doesn't work for me.

The following code is valid,

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
}
Copy after login

My pruned main function,

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)
}
Copy after login

AddTaskFunction,

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 %d\n", projectID)
            return
        case err != nil:
            log.Fatalf("Query error: %v\n", err)
        default:
            log.Printf("Got project %v with id %d\n", 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)
    }
}
Copy after login

In add_task.html, if I put the following placeholder, it is able to populate the start date when I click on http://localhost:8080/project/1/add-task,

<input type="date" id="start_date" name="start_date" value="{{.FormattedStartDate}}">
Copy after login

However, if I replace the following first line in AddTask(),

tmpl := template.Must(template.ParseFiles("static/add_task.html"))
Copy after login

with the one below,

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"))
Copy after login

If I change add_task.html as follows,

<input type="date" id="start_date" name="start_date" value="{{.TaskDetails.StartDate | startdate}}">
Copy after login

When I hit http://localhost:8080/project/1/add-task I get an empty response (but I get 200 OK)

I also mentioned the following questions without success,

https://stackoverflow.com/a/35550730/8813473

Workaround

As @icza mentioned in the comments, from Template.Execute() The error received reveals the problem.

I get an error, template: "" is an incomplete or empty template

Referencehttps://www.php.cn/link/949686ecef4ee20a62d16b4a2d7ccca3's answer, I changed template .New("") Call template.New( "add_task.html") to solve this problem.

The final code is as follows,

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"))
Copy after login

The above is the detailed content of Golang templates: Using FuncMap with html/template produces empty response. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!