You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go HTML模板中同时传递多组变量实现页面多条件渲染?

Fixing Nested Rendering & Data Passing Issues in Go Template Execution

Let's break down what's going wrong here and fix it step by step:

Key Problems in Your Current Code

  1. Duplicate Request Method Check: The second if r.Method != http.MethodPost block will never run—you already return after the first check for GET requests, so your vehicle list is never passed to the template when it matters.
  2. Inconsistent Data Types: You're trying to pass two separate data structures (conditionsMap and carSlice) to the same template. Each Execute call overwrites the template context, and the template can't access both values from different sources at once.

Step 1: Define a Unified Template Data Struct

Create a struct that holds all the data your template needs. This lets you pass both the username and vehicle list in a single, consistent payload:

type TemplateData struct {
    Username string
    Vehicles []Vehicle
}

Step 2: Rewrite the RemoveVehicle Handler

Adjust your handler to use this struct, fix the request flow, and ensure all necessary data is passed to the template in one execution:

func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
    // Initialize our template data container
    data := TemplateData{}
    
    // Populate username from token
    username, _ := ExtractTokenUsername(r)
    data.Username = username

    // Parse template (for better performance, cache this globally instead of parsing on each request)
    t, err := template.ParseFiles("remove.html")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // Handle GET request: render the form with vehicle data (if user is logged in)
    if r.Method == http.MethodGet {
        if username != "" {
            // Connect to database
            db, err := sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
            if err != nil {
                fmt.Println("Connection Failed.")
                panic(err.Error())
            }
            defer db.Close()

            var carSlice []Vehicle
            // Fetch ONLY the current user's vehicles (added WHERE clause for security)
            sqlStatement := `SELECT * FROM Vehicle WHERE Username = ?`
            rows, err := db.Query(sqlStatement, username)
            if err != nil {
                panic(err)
            }
            defer rows.Close()

            for rows.Next() {
                var car Vehicle
                // Ensure scan order matches your Vehicle struct's field order!
                err := rows.Scan(&car.Id, &car.Date, &car.Brand, &car.Model, &car.Mileage, &car.Year, &car.rented, &car.Dayrate)
                if err != nil {
                    panic(err)
                }
                carSlice = append(carSlice, car)
            }
            data.Vehicles = carSlice
        }

        // Execute template ONCE with all our combined data
        t.Execute(w, data)
        return
    }

    // Handle POST request: process vehicle deletion
    if r.Method == http.MethodPost {
        if username == "" {
            http.Error(w, "Access Denied", http.StatusForbidden)
            return
        }

        db, err := sql.Open("mysql", "root:*******@tcp(127.0.0.1:3306)/my_db")
        if err != nil {
            fmt.Println("Connection Failed.")
            panic(err.Error())
        }
        defer db.Close()

        id_ := r.FormValue("select")
        fmt.Println(id_)
        // Add Username check to prevent deleting other users' vehicles
        stmt, e := db.Prepare("DELETE FROM vehicle WHERE id=? AND Username = ?")
        ErrorCheck(e)
        _, err = stmt.Exec(id_, username)
        if err != nil {
            panic(err)
        }

        // Redirect back to the remove page after successful deletion
        http.Redirect(w, r, "/remove", http.StatusSeeOther)
        return
    }

    // Catch-all for unsupported HTTP methods
    http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

Step 3: Update the HTML Template

Adjust the template to access the vehicle list from the Vehicles field of our struct:

{{if .Username}}
 <div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
 <hr style="height:5px">
 <form action="/remove" method="POST" source="custom" name="form">
 <input type="hidden" name="xss-token" value=""/>
 <div class="form-group">
 <div>
 <label class="addV_label">Select Vehicle&nbsp;</label>
 <select name="select" class="form-control loginInput2" required="required">
 {{range .Vehicles}}
 <option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
 {{end}}
 </select>
 </div>
 </div>
 <div>
 <button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
 </div>
 </form>
{{else}}
 <p> Access Denied, please login.<a href="/login">Login</a></p>
{{end}}

Key Improvements

  • Single Template Execution: We now pass all necessary data in one struct and execute the template once, eliminating nested rendering issues.
  • Secure Database Queries: Added Username checks to both vehicle fetch and deletion queries to prevent users from accessing or modifying other users' vehicles.
  • Cleaner Request Flow: Separated GET and POST logic clearly, with a redirect after deletion to avoid form resubmission issues.

内容的提问来源于stack exchange,提问作者Giuseppe Marziano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:32:43