2015-06-13 66 views
7

處理模板的錯誤習慣的方法說我有一個html/template類似如下:在golang

<html> 
<body> 
    <p>{{SomeFunc .SomeData}}</p> 
</body> 

有時SomeFunc返回一個錯誤。有沒有一種慣用的方式來處理這個問題?

如果我直接寫入ResponseWriter,那麼在我遇到錯誤之前已經寫入了狀態碼200。

var tmpl *template.Template 

func Handler(w http.ResponseWriter, r *http.Request) { 
    err := tmpl.Execute(w, data) 
    // "<html><body><p>" has already been written... 
    // what to do with err? 
} 

最好我會返回一個狀態碼400或一些這樣的,但我不能看到一個辦法做到這一點,如果我直接在ResponseWriter使用template.Execute。有什麼我失蹤?

回答

6

由於模板引擎即時生成輸出,所以在SomeFunc調用之前的模板部分已經發送到輸出。如果輸出沒有被緩衝,它們(連同HTTP 200狀態)可能已經被髮送。

你無法對此做任何事情。

你可以做的是在你致電template.Execute()之前進行檢查。在微不足道的情況下,撥打SomeFunc()並檢查其返回值就足夠了。如果選擇此路徑並且返回值SomeFunc()很複雜,則不必從模板中再次調用它,只需將其返回值傳遞給傳遞給模板的參數並在模板中引用此值(所以SomeFunc()將不必執行兩次)。

如果這還不夠或者你無法控制它,你可以創建一個bytes.Buffer,執行你的模板直接進入這個緩衝區,並且在Execute()返回後,檢查是否有錯誤。如果有錯誤,請發回正確的錯誤消息/頁面。如果一切正常,您可以將緩衝區的內容發送到ResponseWriter

這可能是這個樣子:

buf := &bytes.Buffer{} 
err := tmpl.Execute(buf, data) 
if err != nil { 
    // Send back error message, for example: 
    http.Error(w, "Hey, Request was bad!", http.StatusBadRequest) // HTTP 400 status 
} else { 
    // No error, send the content, HTTP 200 response status implied 
    buf.WriteTo(w) 
} 
+3

我** [寫這個(http://elithrar.github.io/article/approximating-html-template-inheritance/)**一而通過'sync.Pool'或其他構造返回緩衝池 - 是解決這個問題的稍微更高效的方法。分配池,獲取緩衝區,寫入緩衝區,然後寫入響應(無錯誤),然後將緩衝區放回池中。否則,你是在點! – elithrar