1. 程式人生 > >Go使用Text和HTML模板

Go使用Text和HTML模板

簡介

Go的兩個包text/templatehtml/template提供了將變數的值替換到文字的機制。通常用在一些printf應付不了的、需要複雜的格式化的場合。

模板的使用

模板規則

Action

模板是一個包含了一個或多個雙花括號標記{{...}})的字串,這種雙花括標記號叫做Action。模板中所有的除Action的字串都按照原樣列印,Action則表現了特殊的行為。通過Action可以列印變數的值、欄位的值、呼叫函式或方法、表達控制流程等。

Dot

Action中的點(.)表示當前值。初始值為傳遞給模板的引數。

API

  • text/template與html/template提供了相同的API來建立、解析和執行模板,區別是html/template提供了HTML轉義。

    // 建立一個名字為name的模板
    func New(name string) *Template
    
    // 解析模板字串
    func (t *Template) Parse(text string) (*Template, error)
    // 解析檔案
    func ParseFiles(filenames ...string) (*Template, error)
    
    // 執行模板,將結果寫入wr
    func (t *Template) Execute(wr io.Writer, data interface{}) error
  • 在確定模板可以正確解析的場合,可以使用Must()來處理Parse()的結果。如果Parse()失敗,則呼叫panic(),如果成功,返回Template物件。

    func Must(t *Template, err error) *Template
  • Funcs()用來註冊函式給模板,註冊之後模板就可以通過名字呼叫外部函數了(見下面例子)。

    func (t *Template) Funcs(funcMap FuncMap) *Template
    
    type FuncMap map[string]interface{}
  • 輸入

例子

最基本的使用

package main

import (
    "log"
    "os"
    "text/template" // 引入包,如果處理HTML,則為 "html/template"
)

func
main() { // 建立一個名字為report的模板,並解析一個字串 t, err := template.New("report").Parse("I am {{.}} years old.") if err != nil { log.Fatal(err) } // 執行模板,5作為引數傳遞,將結果寫到標準輸出 t.Execute(os.Stdout, 5) // 列印結果:I am 5 years old. }

訪問複合資料結構的值

訪問結構體欄位需要在點(.)後面加欄位名。
訪問Map值需要在點(.)後面加Key的值。

package main

import (
    "os"
    "text/template"
)

func main() {
    t := template.Must(
        template.New("report").Parse("I am {{.Age}} years old.\n"))
    t.Execute(os.Stdout, struct{ Age int }{5})
    t.Execute(os.Stdout, map[string]int{"Age": 5})
}

需要注意的是template訪問結構體欄位時利用了反射機制,因此必須匯出欄位才能在模板裡訪問。

迴圈

使用{{range}}{{end}}來表示迴圈。每次迭代中點(.)代表當前迭代的值。

package main

import (
    "os"
    "text/template"
)

func main() {
    const temStr = "{{range .}}{{.}}\n{{end}}"
    t := template.Must(template.New("report").Parse(temStr))
    t.Execute(os.Stdout, []string{"Hello", "Gopher"})
}

管道

|將其左邊的輸出作為其右邊的輸入。

package main

import (
    "os"
    "text/template"
)

func main() {
    const temStr = `{{. | printf "% 10s"}}`
    t := template.Must(template.New("report").Parse(temStr))
    t.Execute(os.Stdout, "Gopher")
}

呼叫函式

如果在模板中需要呼叫函式,則在Parse()之前需要通過Funcs()來註冊。

package main

import (
    "os"
    "text/template"
)

func greet(name string) string {
    return "Hello, " + name + "!"
}

func main() {
    const temStr = `{{. | greet}}`
    t := template.Must(template.New("report").
        Funcs(template.FuncMap{"greet": greet}).
        Parse(temStr))
    t.Execute(os.Stdout, "Gopher")
}

生成動態HTML

  • HTML檔案:time.html

    <html>
        <body>
            <p>Current time is: {{.}}</p>
        </body>
    </html>
  • go檔案:

    package main
    
    import (
        "html/template"
        "log"
        "net/http"
        "time"
    )
    
    func main() {
        http.HandleFunc("/time", timeHandler)
        log.Fatal(http.ListenAndServe(":9090", nil))
    }
    
    func timeHandler(w http.ResponseWriter, r *http.Request) {
        t := template.Must(template.ParseFiles("time.html"))
        t.Execute(w, time.Now().Format("2006-01-02 15:04:05"))
    }