Home  >  Article  >  Backend Development  >  Golang templates: Using FuncMap with html/template produces empty response

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

王林
王林forward
2024-02-12 11:24:071088browse

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
}

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)
}

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)
    }
}

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}}">

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

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

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"))

If I change add_task.html as follows,

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

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"))

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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete