網站首頁 編程語言 正文
場景
現在的項目,基本都是前后端分離,后端只要提供Json等格式的數據就行。在這個背景下,模板渲染這個功能備受冷落,很少會在項目中用到。
雖然在 http 服務中,模板解析不常用,但日常開發中,巧妙利用模板生成代碼,能使我們開發事半功倍。比如:
- 使用模板初始化項目。比如我們每次新建一個 http 服務,可能都需要 promethue 監控、日志等模塊。每次都實現一遍不現實,(或者 copy 別的項目),我們可以寫好模板,支持自定義項目名,初始化新項目。
- 生成代碼。比如之前文章提到的 mockery,就是解析 interface 的語法樹,利用模板生成 Mock 對象。
text/template 包
基本用法
text/template
提供的接口和html/template
包一樣,只不過后者會為 html 格式的輸出做轉義,避免攻擊。
text/template 用法很簡單:
func main() { // 要注入的變量 type Inventory struct { Material string Count uint } sweaters := Inventory{"wool", 17} // 模板內容, {{.xxx}} 格式的都會被注入的變量替換 text := `{{.Count}} items are made of {{.Material}}` TestTemplate(text, sweaters) } func TestTemplate(text string, data interface{}) { // 初始化,解析 tmpl, err := template.New("test").Parse(text) if err != nil { panic(err) } // 輸出到 os.Stdout err = tmpl.Execute(os.Stdout, data) if err != nil { panic(err) } }
結果輸出如下:
17 items are made of wool
其中,Execute
的聲明為:
// 第一個參數是輸出的接口,第二個參數是要注入的數據 func (t *Template) Execute(wr io.Writer, data interface{}) error
第二個參數 data 是 interface{},類型不限,可以是:
- 結構體,屬性在模板中用 {{.Field}} 表示。
- map,value 在模板中用 {{.Key}} 表示。
- 其他簡單類型(int、string等),在模板中用{{.}}表示。
// data 為 map m := map[string]interface{}{"Material": "wool", "Count": 17} TestTemplate(`{{.Count}} items are made of {{.Material}}`, m) // 輸出:17 items are made of wool // data 為 int,{{.}} 代表注入的變量 TestTemplate(`{{.}} items`, 17) // 輸出:17 items
另外,我們也可以使用 template.Must
來檢測返回的 error, 如果 error 不為 nil 則 panic。也就是說下面的代碼:
tmpl, err := template.New("test").Parse(text) if err != nil { panic(err) }
等價于:
tmpl := template.Must(template.New("test").Parse(txt))
我們重點介紹一下,Parse
的參數(代碼中的text
變量),也就是模板的內容。
模板語法
模板里{{xxx}}
格式稱之為 Action,默認以{{
和}}
作為分界符,表示模板的流程控制、或者變量。
空白字符
如果 Action 以 {{-
開頭,會把 action 左邊的空白字符刪除,這里的空白字符包括空格、換行、tab等。同理,-}}
會把右邊的空白字符刪除。如:
d := struct{ Name string }{"Neil"} TestTemplate(`name = {{.Name}} ;`, d) // 輸出:name = Neil ; // 刪除掉 .Name 左邊的空格 TestTemplate(`name = {{- .Name}} ;`, d) // 輸出:name =Neil ; // 刪除掉 .Name 右邊的空格 TestTemplate(`name = {{.Name -}} ;`, d) // 輸出:name = Neil; // 刪除掉 .Name 兩邊的空格 TestTemplate(`name = {{- .Name -}} ;`, d) // 輸出:name =Neil;
常用 Action
備注,格式為 {{/*xxxx*/}}
,注意備注的內容是可以換行的。
text := `{{/*this is a comment*/}} name : {{.}} ` TestTemplate(text, "Neil") // 輸出: // name : Neil
遍歷,可以使用 range 關鍵字。遍歷的變量只能是 slice、array、map 或者 channel。
下面代碼中的 {{.}}
代表 .MapContent
的元素。
d1 := struct{ MapContent []string }{MapContent: []string{"neil", "garmen", "ray"}} text = "{{range .MapContent}}{{.}} {{end}}" TestTemplate(text, d1) // 輸出: // neil garmen ray
注意,這時候的.
不是代表d1
變量,如果希望在 range 塊里面使用d1
, 需要使用 {{$.}}
。
另外也可以使用自定義變量來遍歷:
text = "{{range $i,$v := .MapContent}}{{$i}}=>{{$v}} {{end}}" TestTemplate(text, d1) // 輸出 // 0=>neil 1=>garmen 2=>ray
if-else,變量為零值,或者空 slice、array、map,就相當于是 false。
text = `{{if .Name}}emtpy{{else}}not empty{{end}}` d = struct{ Name string }{"Neil"} TestTemplate(text, d) // 輸出: empty
if 還可以配合 and、or、not 使用:
// .condition1 && .condition2 if and .condition1 .condition2 // .condition1 || .condition2 if or .condition1 .condition2 // !.condition if not .condition
with-else, 和if基本一樣。區別是,with 作用域的 {{.}}
代表 with 參數,而不是全局的 {{.}}
.
text = "{{with .Name}}{{.}}{{else}}empty{{end}}" d = struct{ Name string }{"Neil"} TestTemplate(text, d) // 輸出: Neil
自定義模板,使用 define
定義,template
引用。
text = `{{define "T1"}}ONE{{end}} {{define "T2"}}TWO{{end}} {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}} {{template "T3"}}` TestTemplate(text, nil) // 輸出: ONE TWO
函數
模板提供了一些函數,如上文的and
、or
、not
。比如下文的 index 函數,打印 MapContent 的 index 為 1 的元素。
text = `{{index .MapContent 1}}` d1 = struct{ MapContent []string }{MapContent: []string{"neil", "garmen", "ray"}} TestTemplate(text, d1) // 輸出:garmen
另外,函數還能以管道的方式,一個函數的結果,作為另一個參數的輸入,如 {{func1 args | func2 }}
。還有可以使用自定義函數,詳情可以查看官方文檔:pkg.go.dev/text/templa…。
總結
text/template 功能挺多,本文只是大致介紹一下,詳情還得移步官網
原文鏈接:https://juejin.cn/post/7174364757435088933
相關推薦
- 2022-10-13 Windows命令批處理的用法詳解_DOS/BAT
- 2022-09-15 C語言實現學生成績管理系統課程設計_C 語言
- 2022-12-30 React淺析Fragments使用方法_React
- 2022-03-16 .net?6項目實現壓縮發布_實用技巧
- 2022-10-19 使用docker安裝elk的詳細步驟_docker
- 2022-05-24 C#?JWT權限驗證的實現_C#教程
- 2022-04-27 bash?shell獲取當前腳本的絕對路徑(pwd/readlink)_linux shell
- 2022-04-03 詳解iOS?實現一對多代理方案_IOS
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支