GO語言html模板


模板

一個模板是一個字符串或一個文件,里面包含了一個或多個由雙花括號包含的{{action}}對象。大部分的字符串只是按面值打印,但是對於actions部分將觸發其它的行為。每個actions都包含了一個用模板語言書寫的表達式,一個action雖然簡短但是可以輸出復雜的打印值,模板語言包含通過選擇結構體的成員、調用函數或方法、表達式控制流if-else 語句range循環語句,還有其它實例化模板等諸多特性。Action內部不能有換行,但注釋可以有換行。

示例

模板執行時會遍歷結構並將指針表示為’.‘(稱之為”dot”)指向運行過程中數據結構的當前位置的值。
用作模板的輸入文本必須是utf-8編碼的文本。
Html示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <p>Hello {{.}}!</p>
</body>
</html>

GO server端:

func sayHi(w http.ResponseWriter,r *http.Request)  {
    // 解析指定文件生成模板對象
    tem,err := template.ParseFiles("xx/hello.html")
    if err != nil{
        fmt.Println("讀取文件失敗,err",err)
        return
    }
    // 利用給定數據渲染模板,並將結果寫入w
    tem.Execute(w,"Ares")
}
func main()  {
    http.HandleFunc("/",sayHi)
    err := http.ListenAndServe("127.0.0.1:8888",nil)
    if err != nil{
        fmt.Println("監聽失敗,err",err)
        return
    }
}

效果:

模板語法

模板語法都包含在{{和}}中間,其中{{.}}中的點表示當前對象。
當我們傳入一個結構體對象時,我們可以根據.來訪問結構體的對應字段。Html示例:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>
    <p>Hello {{.Name}}!</p>
    <p>年齡 {{.Age}}!</p>
    <p>性別 {{.Male}}!</p>
</body>
</html>

GO server端:

type People struct {
    Name string
    Age int
    Male string
}
func sayHi(w http.ResponseWriter,r *http.Request)  {
    // 解析指定文件生成模板對象
    tem,err := template.ParseFiles("xx/hello.html")
    if err != nil{
        fmt.Println("讀取文件失敗,err",err)
        return
    }
    // 利用給定數據渲染模板,並將結果寫入w
    People := People{
        Name:"Ares",
        Age:28,
        Male:"男",
    }
    tem.Execute(w,People)
}
func main()  {
    http.HandleFunc("/",sayHi)
    err := http.ListenAndServe("127.0.0.1:8888",nil)
    if err != nil{
        fmt.Println("監聽失敗,err",err)
        return
    }
}

效果:

注釋

{{/* a comment */}}
可以多行。注釋不能嵌套。

變量

Action里可以初始化一個變量來捕獲管道的執行結果。初始化語法如下:

$variable := pipeline

示例:

<body>
    <p>Hello {{.Name}}!</p>
    <p>年齡 {{.Age}}!</p>
    <p>性別 {{.Male}}!</p>
    {{ $age := . }}
    {{ $age.Age }}
</body>

條件判斷

初始語法:

{{if pipeline}} T1 {{end}}
{{if pipeline}} T1 {{else}} T0 {{end}}
{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}

示例:

<body>
    <p>Hello {{.Name}}!</p>
    <p>年齡 {{.Age}}!</p>
    <p>性別 {{.Male}}!</p>
    {{ $age := . }}
    {{ $age.Age }}
    {{if gt .Age 18}}
    <div>成年啦!</div>
    {{else}}
    <div>快樂成長!</div>
    {{end}}
</body>

比較函數

布爾函數會將任何類型的零值視為假,其余視為真。

eq      如果arg1 == arg2則返回真
ne      如果arg1 != arg2則返回真
lt      如果arg1 < arg2則返回真
le      如果arg1 <= arg2則返回真
gt      如果arg1 > arg2則返回真
ge      如果arg1 >= arg2則返回真

range

使用range關鍵字進行遍歷,有以下兩種寫法,其中pipeline的值必須是數組、切片、字典或者通道。
基本語法:

{{range pipeline}} T1 {{end}}
如果pipeline的值其長度為0,不會有任何輸出

{{range pipeline}} T1 {{else}} T0 {{end}}
如果pipeline的值其長度為0,則會執行T0。

map示例:

PeopleMap := map[int]People{
        1: {"Ares", 18, "男"},
        2: {"龍貓", 28, "女"},
    }
tem.Execute(w, PeopleMap)

切片示例:

PeopleSlice := []People{
        {"Ares", 18, "男"},
        {"龍貓", 28, "女"},
    }
    tem.Execute(w, PeopleSlice)

HTML模板:

<body>
<table border="1">
    <thead>
    <tr>
        <th>序號</th>
        <th>姓名</th>
        <th>年齡</th>
        <th>性別</th>
    </tr>
    </thead>
    <tbody>
    {{range $index, $user := .}}
    <tr>
        <td>{{$index}}</td>
        <td>{{$user.Name}}</td>
        <td>{{$user.Age}}</td>
        <td>{{$user.Male}}</td>
    </tr>
    {{end}}
    </tbody>
</table>
</body>

效果:

預定義函數

執行模板時,函數從兩個函數字典中查找:首先是模板函數字典,然后是全局函數字典。一般不在模板內定義函數,而是使用Funcs方法添加函數到模板里。

and
    函數返回它的第一個empty參數或者最后一個參數;
    就是說"and x y"等價於"if x then y else x";所有參數都會執行;
or
    返回第一個非empty參數或者最后一個參數;
    亦即"or x y"等價於"if x then x else y";所有參數都會執行;
not
    返回它的單個參數的布爾值的否定
len
    返回它的參數的整數類型長度
index
    執行結果為第一個參數以剩下的參數為索引/鍵指向的值;
    如"index x 1 2 3"返回x[1][2][3]的值;每個被索引的主體必須是數組、切片或者字典。
print
    即fmt.Sprint
printf
    即fmt.Sprintf
println
    即fmt.Sprintln
html
    返回其參數文本表示的HTML逸碼等價表示。
urlquery
    返回其參數文本表示的可嵌入URL查詢的逸碼等價表示。
js
    返回其參數文本表示的JavaScript逸碼等價表示。
call
    執行結果是調用第一個參數的返回值,該參數必須是函數類型,其余參數作為調用該函數的參數;
    如"call .X.Y 1 2"等價於go語言里的dot.X.Y(1, 2);
    其中Y是函數類型的字段或者字典的值,或者其他類似情況;
    call的第一個參數的執行結果必須是函數類型的值(和預定義函數如print明顯不同);
    該函數類型值必須有1到2個返回值,如果有2個則后一個必須是error接口類型;
    如果有2個返回值的方法返回的error非nil,模板執行會中斷並返回給調用模板執行者該錯誤;

參考:GO語言標准庫
示例:

<p>{{index . 1}}</p>
    <p>切片長度: {{len .}}</p>
    <p>
        {{with index . 1}}
        {{printf "姓名:%s 年齡:%d 性別:%s" .Name .Age .Male}}
        {{end}}
    </p>

效果:

自定義函數

自定義一個book函數:

type Book struct {
    Name string
    Author string
    Price float32
}

func info(w http.ResponseWriter,r *http.Request)  {
    // 打開一個模板文件
    htmlByte,err := ioutil.ReadFile("./info.html")
    if err != nil{
        fmt.Println("讀取html文件失敗,err",err)
        return
    }
    // 1. 自定義一個函數
    // 自定義一個書籍的模板函數
    bookFunc := func(arg string) (string, error) {
        return arg + "真好看!", nil
    }
    // 2. 把自定義的函數告訴模板系統
    // template.New("info") // 創建一個Template對象
    // template.New("info").Funcs(template.FuncMap{"book": bookFunc}) // 給模板系統追加自定義函數
    // 解析模板
    t,err := template.New("info").Funcs(template.FuncMap{"book": bookFunc}).Parse(string(htmlByte))
    if err != nil{
        fmt.Println("parse html文件失敗,err",err)
        return
    }
    BookMap := map[int]Book{
        1:{"跟Ares一起學GO","Ares",9.9},
        2:{"斗破蒼穹","Ares1",99.9},
    }
    t.Execute(w,BookMap)
}

func main()  {
    http.HandleFunc("/info",info)
    http.ListenAndServe("127.0.0.1:8888",nil)
}

html:

<body>
    <p>
    {{with index . 1}}
    <p>{{book .Name}}</p>
    {{end}}
    </p>
    <p>
    {{with index . 2}}
    <p>{{book .Name}}</p>
    {{end}}
    </p>
</body>

效果:

模板嵌套

我們可以在template中嵌套其他的template。這個template可以是單獨的文件,也可以是通過define定義的template.

func index(w http.ResponseWriter,r * http.Request)  {
    t , err := template.ParseFiles("./index.html","./test.html")
    if err != nil{
        fmt.Println("讀取html文件失敗,err",err)
        return
    }
    t.Execute(w,nil)
}
func main()  {
    http.HandleFunc("/",index)
    http.ListenAndServe("127.0.0.1:8888",nil)
}

index.html:

<body>
<h1>測試嵌套template語法</h1>
<hr>
{{template "test.html"}}
<hr>
{{/* 在index.html這個模板中調用了另外一個模板:index.html */}}
{{template "inside.html"}}
</body>
</html>
        
{{/* 在index.html這個模板中定義了另外一個模板:inside.html */}}
{{ define "inside.html"}}
<h1>inside.html</h1>
<ol>
    <li>吃飯</li>
    <li>睡覺</li>
    <li>打豆豆</li>
</ol>
{{end}}

test.html:

<body>
<ol>
    <li>嵌套模板</li>
    <li>out模板</li>
</ol>
</body>

效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM