2 回答

TA貢獻(xiàn)1890條經(jīng)驗(yàn) 獲得超9個(gè)贊
我們來(lái)分析一下性能:
我們將您的第一個(gè)解決方案(略有變化,見(jiàn)下文)命名為a和您的第二個(gè)解決方案b。
一個(gè)請(qǐng)求:
a:一個(gè)磁盤訪問(wèn)
b:一個(gè)磁盤訪問(wèn)
十次請(qǐng)求:
a:一次磁盤訪問(wèn)
b:十次磁盤訪問(wèn)
10 000 000 次請(qǐng)求:
a:一次磁盤訪問(wèn)
b:10 000 000 次磁盤訪問(wèn)(這很慢)
因此,第一個(gè)解決方案的性能更好。但是您對(duì)最新數(shù)據(jù)的擔(dān)憂呢?從文檔func (t *Template) Execute(wr io.Writer, data interface{}) error
:
Execute 將解析的模板應(yīng)用于指定的數(shù)據(jù)對(duì)象,將輸出寫入 wr。如果在執(zhí)行模板或?qū)懭肫漭敵鰰r(shí)發(fā)生錯(cuò)誤,則執(zhí)行將停止,但部分結(jié)果可能已寫入輸出寫入器。模板可以安全地并行執(zhí)行。
所以,發(fā)生的事情是這樣的:
您從磁盤讀取模板
您將文件解析為模板
您選擇的數(shù)據(jù)填補(bǔ)空白與
您
Execute
使用具有該數(shù)據(jù)的模板,結(jié)果將寫入io.Writer
您選擇的數(shù)據(jù)是最新的。這與從磁盤重新讀取模板,甚至重新解析它無(wú)關(guān)。這是模板背后的整個(gè)想法:一次磁盤訪問(wèn),一次解析,多個(gè)動(dòng)態(tài)最終結(jié)果。
上面引用的文檔告訴我們另一件事:
模板可以安全地并行執(zhí)行。
這非常有用,因?yàn)槟?code>http.HandlerFuncs 是并行運(yùn)行的,如果您有多個(gè)并行請(qǐng)求。
那么,現(xiàn)在該怎么辦?Read
模板文件一次,Parse
模板一次,每個(gè)請(qǐng)求Execute
的模板。
我不確定您是否應(yīng)該在init()
函數(shù)中讀取和解析,因?yàn)橹辽?code>Must可以恐慌(并且不要在那里使用一些相對(duì)的硬編碼路徑?。?- 我會(huì)嘗試在更受控的環(huán)境中這樣做,例如,提供一個(gè)函數(shù)(如New()
)來(lái)創(chuàng)建服務(wù)器的新實(shí)例并在其中執(zhí)行這些操作。
編輯:我重新閱讀了你的問(wèn)題,我可能誤解了你:
如果模板本身仍在開(kāi)發(fā)中,那么是的,您必須在每個(gè)請(qǐng)求中閱讀它才能獲得最新的結(jié)果。這比每次更改模板時(shí)都重新啟動(dòng)服務(wù)器更方便。對(duì)于生產(chǎn),模板應(yīng)該是固定的,只有數(shù)據(jù)應(yīng)該改變。
對(duì)不起,如果我在那里弄錯(cuò)了。

TA貢獻(xiàn)1895條經(jīng)驗(yàn) 獲得超3個(gè)贊
永遠(yuǎn)不要在生產(chǎn)中的請(qǐng)求處理程序中讀取和解析模板文件,這是最糟糕的(你應(yīng)該總是避免這種情況)。在開(kāi)發(fā)過(guò)程中當(dāng)然是可以的。
閱讀此問(wèn)題了解更多詳情:
golang中使用“模板”包生成動(dòng)態(tài)網(wǎng)頁(yè)給客戶端的時(shí)間太長(zhǎng)了
你可以通過(guò)多種方式來(lái)解決這個(gè)問(wèn)題。在這里,我列出了 4 個(gè)示例實(shí)現(xiàn)。
1.帶有“開(kāi)發(fā)模式”設(shè)置
如果您在開(kāi)發(fā)模式下運(yùn)行,您可以有一個(gè)常量或變量告訴您,這意味著模板不會(huì)被緩存。
這是一個(gè)例子:
const dev = true
var indexTmpl *template.Template
func init() {
if !dev { // Prod mode, read and cache template
indexTmpl = template.Must(template.New("index").ParseFiles(".tpl/index.tpl"))
}
}
func getIndexTmpl() *template.Template {
if dev { // Dev mode, always read fresh template
return template.Must(template.New("index").ParseFiles(".tpl/index.tpl"))
} else { // Prod mode, return cached template
return indexTmpl
}
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
getIndexTmpl().Execute(w, "test")
}
2. 在請(qǐng)求中指定(作為參數(shù))是否需要新模板
開(kāi)發(fā)時(shí),您可以指定一個(gè)額外的 URL 參數(shù),指示讀取新模板而不使用緩存的模板,例如 http://localhost:8080/index?dev=true
示例實(shí)現(xiàn):
var indexTmpl *template.Template
func init() {
indexTmpl = getIndexTmpl()
}
func getIndexTmpl() *template.Template {
return template.Must(template.New("index").ParseFiles(".tpl/index.tpl"))
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
t := indexTmpl
if r.FormValue("dev") != nil {
t = getIndexTmpl()
}
t.Execute(w, "test")
}
3.根據(jù)主機(jī)決定
您還可以檢查請(qǐng)求 URL 的主機(jī)名,如果是"localhost",則可以省略緩存并使用新模板。這需要最少的額外代碼和努力。請(qǐng)注意,您可能還想接受其他主機(jī),例如"127.0.0.1"(取決于您想要包含的內(nèi)容)。
示例實(shí)現(xiàn):
var indexTmpl *template.Template
func init() {
indexTmpl = getIndexTmpl()
}
func getIndexTmpl() *template.Template {
return template.Must(template.New("index").ParseFiles(".tpl/index.tpl"))
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
t := indexTmpl
if r.URL.Host == "localhost" || strings.HasPrefix(r.URL.Host, "localhost:") {
t = getIndexTmpl()
}
t.Execute(w, "test")
}
4.檢查模板文件最后修改
您還可以存儲(chǔ)模板文件加載時(shí)的最后修改時(shí)間。每當(dāng)請(qǐng)求模板時(shí),您可以檢查源模板文件的最后修改時(shí)間。如果它已更改,您可以在執(zhí)行之前重新加載它。
示例實(shí)現(xiàn):
type mytempl struct {
t *template.Template
lastmod time.Time
mutex sync.Mutex
}
var indexTmpl mytempl
func init() {
// You may want to call this in init so first request won't be slow
checkIndexTempl()
}
func checkIndexTempl() {
nm := ".tpl/index.tpl"
fi, err := os.Stat(nm)
if err != nil {
panic(err)
}
if indexTmpl.lastmod != fi.ModTime() {
// Changed, reload. Don't forget the locking!
indexTmpl.mutex.Lock()
defer indexTmpl.mutex.Unlock()
indexTmpl.t = template.Must(template.New("index").ParseFiles(nm))
indexTmpl.lastmod = fi.ModTime()
}
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
checkIndexTempl()
indexTmpl.t.Execute(w, "test")
}
- 2 回答
- 0 關(guān)注
- 191 瀏覽
添加回答
舉報(bào)