【问题标题】:Multiple response.WriteHeader calls多个 response.WriteHeader 调用
【发布时间】:2016-06-06 19:12:56
【问题描述】:

我是新手,在渲染模板时遇到了困难。

这是我要生成模板的函数:

base.html

//Render templates for the given name, template definition and data object
func renderTemplate(w http.ResponseWriter, name string, template string, viewModel interface{}) {
    // Ensure the template exists in the map.
    tmpl, ok := templates[name]
    if !ok {
        http.Error(w, "The template does not exist.", http.StatusInternalServerError)
    }
    err := tmpl.ExecuteTemplate(w, template, viewModel)
    if err != nil {
    log.Printf("temlate error here")
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}


 func EditNote(w http.ResponseWriter, r *http.Request) {
    //var viewModel models.EditChnl
    vars := mux.Vars(r)
    //ch := bson.M{"id": "Ale"}
    title := vars["title"]
    log.Printf("%v\n", title)
    session, err := mgo.Dial("localhost")
    if err != nil {
      panic(err)
    }
        defer session.Close()
        session.SetMode(mgo.Monotonic, true)
        c := session.DB("tlgdb").C("chnls")
        log.Printf("title is %s \n", title)
        var result  []models.Chnl
        err = c.Find(bson.M{"title": "xxx"}).All(&result)
        log.Printf("%v\n", result)

        if err != nil {
          log.Printf("doc not found")
          log.Fatal(err)
          return
        }
    renderTemplate(w, "edit", "base", result)
}

这里是模板:

{{define "base"}}
<html>
  <head>
    {{template "head" .}}
  </head>
  <body>

    {{template "body" .}}

  </body>
</html>
{{end}}

edit.thml

{{define "head"}}<title>Edit Note</title>{{end}}
{{define "body"}}
<h1>Edit Note</h1>
<form action="/chnls/update/{{.Title}}" method="post">
<p>Title:<br> <input type="text" value="{{.Title}}" name="title"></p>
<p>Description:<br> <textarea rows="4" cols="50" name="description">{{.Description}}</textarea> </p>
<p><input type="submit" value="submit"/></p>
</form>
{{end}}

要渲染的对象是:

type Chnl struct {
    Id    bson.ObjectId `json:"id"  bson:"_id,omitempty"`
    Title       string
    Description string
    CreatedOn   time.Time
    Creator     string
    Visits  int
    Score       int
}

我要渲染的对象存在于 mongodb 中,我可以在控制台中打印出来:

[{ObjectIdHex("56cc4493bc54f4245cb4d36b") sometitle blabla 2016-02-23 12:37:55.972 +0100 CET blabla 0 0}]

但是我得到了这个错误:

temlate error here
http: multiple response.WriteHeader calls

我想知道这里出了什么问题以及如何解决?

【问题讨论】:

    标签: go go-templates


    【解决方案1】:

    根本问题是您将Chnl 的一部分传递给模板:

    var result  []models.Chnl
    // ...
    renderTemplate(w, "edit", "base", result)
    

    renderTemplate() 内部,viewModel 的参数值将是result

    在您的模板中,您引用点的字段,例如它是否是Chnl 值而不是它的一部分:{{.Title}}。所以第一次尝试解决它会失败。

    记录错误很有用,因此请更改您的记录以同时打印实际错误,而不仅仅是一般错误:

    log.Printf("Temlate error here: %v", err)
    

    结果:

    2016/02/24 14:57:09 此处的模板错误:模板:edit.html:4:30:在 <.title> 处执行“正文”:无法评估 []main.Chnl 类型中的字段标题

    我认为您只想传递 1 个 Chnl 值而不是其中的一部分。在EditNote()

    if len(result) > 0 {
        renderTemplate(w, "edit", "base", result[0])
    }
    

    接下来,知道http.Error() 将内容写入响应。这意味着您无法将更多标头值写入响应。通常,当您在处理程序中调用 http.Error() 时,您应该返回而不对响应执行任何操作:

    if !ok {
        http.Error(w, "The template does not exist.", http.StatusInternalServerError)
        return // NOTE THIS RETURN
    }
    

    同样,在您的所有http.Error() 调用之后插入return。您可以做一些清理工作,但在http.Error() 之后不应触及回复。

    【讨论】:

    • 进一步,如果ExecuteTemplate在写入时遇到错误,则已经写入了状态码和响应头。 http.Error 无法更改它们。您可以通过先执行到缓冲区然后写出响应来解决此问题 (see here for a how-to)
    猜你喜欢
    • 1970-01-01
    • 2014-12-13
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 2019-07-26
    • 1970-01-01
    相关资源
    最近更新 更多