Golang中HTML模板在POST请求时无法正常工作的问题

Golang中HTML模板在POST请求时无法正常工作的问题 whatarethose.go 文件

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    // request switch
    switch r.Method {
    case "GET":     
    	fmt.Println("GET")
        http.ServeFile(w, r, "whatarethose.html")
    case "POST":
            // send name and value to html
	    t, err := template.ParseFiles("whatarethose.html")

	        if err != nil {
			fmt.Println(err)
		}

		items := struct {
			Name string
			Value float64
		}{
			Name: "hi",
			Value: 0.1,
		}

		t.Execute(w, items)
       }
}

whatarethose.html 文件

            <form name="predict" method="POST" action="/" target="hiddenFrame">
                <div class="row half">
                    <div class="6u">
                    <input type="text" id="url" class="text" name="url" placeholder="URL"></textarea>
                    </div>
                </div>
                <div class="row">
                    <div class="12u">
                        <button id="submit" class="button">Submit</button>
                    </div>
                </div>
            </form>

            <br></br>
            <div id="result">
              <img id="loader" style="display:none" src="/images/load.gif"></div>
              <div id="res">
                <p id="info">{{.Name}}<br>{{.Value}}</p>
                <img id="demo" src="">
              </div>
            </div>

以上是我项目中的部分骨架代码。我的网页上有一个表单,提交时会发出 POST 请求。在我的 Go 代码中,我试图将 API 调用的响应作为结构体传回 HTML 页面,以在此处显示:<p id="info">{{.Name}}<br>{{.Value}}</p>。但实际显示的只有字面字符串 {{.Name}}{{.Value}}。然而,当我把 Go 文件中的模板代码移到 GET 情况中或之前时,它可以正常显示任何值,但我没有从 API 调用返回的值,所以我需要在 POST 情况中包含模板代码,但它不起作用。如果有人能告诉我原因以及如何解决这个问题,我将非常感激。谢谢。


更多关于Golang中HTML模板在POST请求时无法正常工作的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

这里似乎缺少了一些内容。根据你的示例,以下修改对我有效:

  • whatarethose.go 中,将 t.Execute() 替换为 t.ExecuteTemplate()。例如:t.ExecuteTemplate(w, "whatarethose", items)
  • whatarethose.html 中,添加 {{define}} 来访问你的数据。例如:
{{define "whatarethose"}}
<p id="info">{{.Name}}<br>{{.Value}}</p>
<img id="demo" src="">
{{ end }}

编辑:我刚意识到这个帖子已经发布一个月了,可能已经不再相关。抱歉!

更多关于Golang中HTML模板在POST请求时无法正常工作的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于你的HTML模板中包含了表单本身,当在POST请求中重新渲染整个页面时,表单会覆盖之前的内容。模板引擎确实在工作,但由于表单仍然存在,它会重新显示模板标签而不是渲染后的值。

以下是修复方案:

修改后的 Go 代码:

func handler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case "GET":     
        fmt.Println("GET")
        http.ServeFile(w, r, "whatarethose.html")
    case "POST":
        // 解析结果模板而不是完整页面
        t, err := template.ParseFiles("result.html")
        if err != nil {
            fmt.Println(err)
            return
        }

        items := struct {
            Name  string
            Value float64
        }{
            Name:  "hi", 
            Value: 0.1,
        }

        t.Execute(w, items)
    }
}

创建新的 result.html 文件:

<div id="result">
    <div id="res">
        <p id="info">{{.Name}}<br>{{.Value}}</p>
        <img id="demo" src="">
    </div>
</div>

修改原来的 whatarethose.html 文件:

<form name="predict" method="POST" action="/" target="hiddenFrame">
    <div class="row half">
        <div class="6u">
            <input type="text" id="url" class="text" name="url" placeholder="URL">
        </div>
    </div>
    <div class="row">
        <div class="12u">
            <button id="submit" class="button">Submit</button>
        </div>
    </div>
</form>

<br>
<div id="result-container">
    <!-- 这里将通过AJAX加载结果 -->
</div>

<iframe name="hiddenFrame" style="display:none"></iframe>

<script>
document.getElementById('submit').addEventListener('click', function(e) {
    e.preventDefault();
    
    // 显示加载动画
    document.getElementById('loader').style.display = 'block';
    
    // 使用AJAX提交表单
    fetch('/', {
        method: 'POST',
        body: new FormData(document.forms.predict)
    })
    .then(response => response.text())
    .then(html => {
        document.getElementById('result-container').innerHTML = html;
        document.getElementById('loader').style.display = 'none';
    });
});
</script>

或者,如果你想要保持当前结构但修复问题,可以使用条件模板:

修改后的单一模板方案:

func handler(w http.ResponseWriter, r *http.Request) {
    t, err := template.ParseFiles("whatarethose.html")
    if err != nil {
        fmt.Println(err)
        return
    }

    data := struct {
        Name  string
        Value float64
        IsPost bool
    }{
        Name:  "hi",
        Value: 0.1,
        IsPost: r.Method == "POST",
    }

    t.Execute(w, data)
}

对应的模板文件:

{{if not .IsPost}}
<form name="predict" method="POST" action="/" target="hiddenFrame">
    <div class="row half">
        <div class="6u">
            <input type="text" id="url" class="text" name="url" placeholder="URL">
        </div>
    </div>
    <div class="row">
        <div class="12u">
            <button id="submit" class="button">Submit</button>
        </div>
    </div>
</form>
{{end}}

<br>
<div id="result">
    {{if .IsPost}}
    <div id="res">
        <p id="info">{{.Name}}<br>{{.Value}}</p>
        <img id="demo" src="">
    </div>
    {{end}}
</div>

第一个方案使用单独的模板文件处理POST响应,第二个方案使用条件逻辑在同一个模板中控制显示内容。两种方案都能解决模板标签不被渲染的问题。

回到顶部