2015-06-13 15 views
7

dire che ho un html/template come la seguente:modo idiomatico per gestire gli errori di modello in golang

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

e talvolta SomeFunc restituisce un errore. C'è un modo idiomatico per affrontare questo?

Se scrivo direttamente allo ResponseWriter, è stato già scritto un codice di stato 200 prima che si verifichi l'errore.

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

Preferibilmente vorrei restituire un codice di stato 400 o qualcosa del genere, ma non riesco a vedere un modo per fare questo se uso template.Execute direttamente sul ResponseWriter. C'è qualcosa che mi manca?

risposta

6

Poiché il motore di template genera l'output al volo, parti del modello che precedono la chiamata SomeFunc sono già state inviate all'output. E se l'output non è bufferizzato, possono essere già inviati (insieme allo stato HTTP 200).

Non puoi farci niente.

Che cosa è possibile fare è eseguire il controllo prima di chiamare template.Execute(). In caso banale dovrebbe essere sufficiente chiamare SomeFunc() e controllare il suo valore di ritorno. Se si sceglie questo percorso e il valore di ritorno di SomeFunc() è complesso, non è necessario richiamarlo nuovamente dal modello, è sufficiente passare il suo valore di ritorno ai parametri che si passano al modello e fare riferimento a questo valore nel modello (quindi SomeFunc() non dovrà essere eseguito due volte).

Se questo non è sufficiente o non è possibile controllarlo, è possibile creare un bytes.Buffer, eseguire il modello diretto in questo buffer e, dopo i ritorni Execute(), verificare se ci sono stati errori. Se ci sono stati degli errori, inviare un messaggio/pagina di errore corretto. Se tutto è andato bene, è sufficiente inviare il contenuto del buffer allo ResponseWriter.

Questo potrebbe essere simile a questa:

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

I ** [scritto su questo] (http://elithrar.github.io/article/approximating-html-template-inheritance/) ** una mentre back-un pool di buffer tramite 'sync.Pool' o un altro costrutto-è un modo leggermente più performante per risolverlo. Assegnare un pool, ottenere un buffer, scrivere su di esso e poi sulla risposta (su errore nullo) e quindi rimettere il buffer nel pool. Altrimenti sei sul punto! – elithrar

Problemi correlati