golang echo 程式碼詳解之模版篇

Laily發表於2017-12-12

在 echo 裡使用模版則必須先註冊一個,如果不註冊就會報出下面這樣的錯誤

{"time":"2017-12-12T23:03:57.939138716+08:00","level":"ERROR","prefix":"echo","file":"echo.go","line":"284","message":"Renderer not registered"}

註冊就是給 echo.Renderer 賦值。

echo 的 Renderer 屬性是一個介面

Renderer interface {
    Render(io.Writer, string, interface{}, Context) error
}

一、使用標準庫模版

echo 的文件給出了使用官方模版註冊的方式

// 實現 Renderer 介面
type Template struct {
    templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
    return t.templates.ExecuteTemplate(w, name, data)
}
// 處理 view 目錄下的檔案生成對應的模版
// 關於 ExecuteTemplate 和 ParseGlob 方法可以檢視 
// https://wizardforcel.gitbooks. ... plate
t := &Template{
    templates: template.Must(template.ParseGlob("public/views/*.html")),
}
// 賦值
e.Renderer = t

二、使用 pongo2

gopkg.in/flosch/pongo2.v3 是一個很不錯的模版引擎,很多時候會選擇它來渲染模版。

首先還是實現 Renderer 介面

type Template struct {
    // 這裡使用一個 map 來儲存預處理了的模版
    tmplMap map[string]*pongo2.Template
}

func (t *Template) Render(w io.Writer, templateName string, data interface{}, c echo.Context) error {
    // 這裡根據傳來的 name 從 tmplMap 裡查詢模版來渲染
    // 注意 ExcuteWriter 的引數必須是 map[string]interface{} 的
    dataMap := data.(map[string]interface{})
    template, exist := t.tmplMap[templateName]
    if !exist {
        return errors.New("template " + templateName + " not found")
    }
    return template.ExecuteWriter(dataMap, w)
}

然後預編譯模版

// 讀取目錄下的檔案預處理
func preCompile(dir string) *Template {
    tmplMap := make(map[string]*pongo2.Template)

    dirPath := filepath.Dir(dir)
    fileInfos, _ := ioutil.ReadDir(dirPath)

    for _, fileInfo := range fileInfos {
        t, err := pongo2.FromFile(path.Join(dir, fileInfo.Name()))
        if err != nil {
            log.Fatalf("\"%s\": %v", fileInfo.Name(), err)
        }
        tmplMap[strings.Replace(fileInfo.Name(), path.Ext(fileInfo.Name()), "", -1)] = t

    }

    return &Template{tmplMap}
}

最後賦值

func NewTemplates(dir string) *Template {
    return preCompile(dir)
}

t := NewTemplates("./views/")
e.Renderer = t

這樣自定義的 renderer 就算完成了。

原文地址:laily.net

相關文章