go语言模板引擎,gtpl使用介绍

go语言模板引擎,gtpl使用介绍,第1张

概述gtpl今天分享一个自己写的go语言模板引擎。方便在go语言输出html渲染时能以极快的速度进行模板语法分析。相比go语言官方库htmlemplate,gtpl的语法有着简练、灵活、易用的特点。gtpl最终的目的就是完全替代go语言官方过于复杂的htmlemplate渲染包,让模板调 gtpl

今天分享一个自己写的 go 语言模板引擎。方便在 go语言输出HTML 渲染时能以极快的速度进行模板语法分析。相比 go 语言官方库 HTML/template,gtpl 的语法有着简练、灵活、易用的特点。

gtpl 最终的目的就是完全替代 go 语言官方过于复杂的 HTML/template 渲染包,让模板调用变得更加灵活,更加适合理解,从而在很大程度上节约开发者的时间。


与 PHP 模板引擎不同之处

gtpl 与 那些基于 PHP 的模板引擎完全不同。

PHP 模板引擎直接将标签语法翻译为 PHP 代码,保存为 PHP 文件之后再重新从 PHP 引入,然后就可以直接运行了。而 gtpl 相当于一个超轻量级的编程语言,它实现了自己的语义分析,因此,从处理方式上有着本质区别。每一个标签的处理都需要使用递归逻辑,并且需要在递归过程中保持上下文。笔者为此付出了大量的工作。

目前,它仍然存在一些不足,比如对于 if 语句的解析存在一些未知问题需要解决,我会在接下来的版本中将会重点关注并修复它们。

gtpl 目前已经可以使用简单的 if 条件表达式,如算术运算、逻辑运算,它对运算符的优先级处理是与 go 语言一样的:

{!if ID==1+2-(10*5/(11))}    123{;elseif ID!=pID}    {!if Title=="hello"}        ...    {/if}{;else}    789{/if}
但对于其中两个逻辑运算符 “&&” 和 “||” 尚未做处理,因此,你暂时不可以使用如下的表达式,它有可能返回一个明确的错误提示,也有可能输出错误的数据。当然大多数情况下,底层是可以捕获这个异常的:
// 在当前版本,这段标签代码不会按照期望顺利运行// this would not work in this version{!if a==1&&b==2}    something{/if}
我将在下一个版本着重处理这个问题。

以下是 gtpl 常用的标签调用示例 (Example):

example a.go
import(    "github.com/pywee/gtpl/handle/templates"    "log"    "net/http")// data// example structtype Data struct {    ID      int64    WebTitle string    Users   []*User    Winner  *Demo}// example structtype Demo struct {	Str string}// example structtype User struct {	ID       int	Username string	MyList   []*UserCustom}type UserCustom struct {    PhoneNumber string}func main() {    // create data that you want to render to HTML    // 组装要渲染到 HTML 的数据    data := &Data{        ID:    1,        WebTitle: "WebTitle",        Winner: &Demo{            Str: "pywee",        },        Users: []*User{            {                ID:       1,                Username: "Jim",                MyList: []*UserCustom{                    {PhoneNumber: "1"},                    {PhoneNumber: "2"},                },            },            {                ID:       2,                Username: "Lucy",                MyList: []*UserCustom{                    {PhoneNumber: "1"},                    {PhoneNumber: "2"},                },            },        },    }    // http server example	http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {		// 实例化gtpl (instantiation gtpl)		p := templates.NewParser()		// 引入模板文件,将 data 数据匹配模板中的调用		re, err := p.Parsefile("example/index.HTML", data)		if err != nil {			panic(err)		}		// print string		// fmt.Println(re.String())		// 输出到屏幕,它的作用相当于 template.Excute(w, "%s", data)		re.Fprint(w)	})}

针对以上代码,你可以用这种方式在HTML文件中获取数据(For the above code, you can get data in HTML file in this way)。

example a.HTML:
<HTML>....// 你可以在这里直接访问data结构体下的字段 // (You can call the fIElds under the structure in this way)// 访问结构体中的 Data.ID, Data.Title  在 HTML 中调用时请注意使用小写,用下划线替代结构体中的驼峰字段// to call ID and WebTitle of struct Data{:ID}{:web_Title}// 访问 Data 结构体中的 Other.Demo.Str// to call Other.Demo.Str of struct Data{:winner.str} // 在访问字段的同时,执行内置函数{:trim(replace(Title, "i am", "xx", -1), "xx")}// 对于列表处理,例如循环 data 下的 users 数组,用如下方式{:ID}{:winner.str}  // 访问 Data 下的 Winner结构体,再访问该结构体下的 Str 字段{!List:users}    {!if ID==(1*1+1-1-1)}        man: {:user_name}    {;elseif 1==21}        women: {:user_name}    {;else}        {!List:my_List}            {:phone_number}        {/List}    {/if}{/List}</HTML>

针对以上标签代码,{!List:users}也可以明确写成 {!List:data.users},但底层处理方法略有不同。
标签中所声明的大多数调用,底层都会像剥大蒜一遍又一遍递归查找、匹配。因此,你应该尽可能使用 {!List:users},即使这样也是以递归的方式处理语法相关的工作,但相比之下,会减少递归的次数。
(You can also use {!List:data.users}to ergodic slice users, but it is not good for performance.)


*此外,必须注意,出于效率考虑,目前 gtpl 并不支持返回结构体的 tag 来获得结构体指定字段的数据,所以,当你在HTML中调用结构体中的字段时,需转为下划线 “_”,而结构体中的字段仍然使用驼峰写法。
如调用结构体中的 Username,在 HTML 文件中需要使用 {:user_name} 来调用。

gtpl 可支持部分 go 语言内置函数的调用:

len()tolower()toupper()replace()trim()ltrim()rtrim()trimspace()// 示例 example{!List:data}    {:trim(Title, "hello")}{/List}

另外,如果传入 Parsefile 函数的数所是一个数组结构,那么你必需在HTML中首先循环它,如:

example
    d2 := []*Data{ // slice		{			ID: 1,			Users: []*User{				{					ID:       2,					Username: "Title",					MyList: []*UserCustom{						{PhoneNumber: "1"},						{PhoneNumber: "2"},						{PhoneNumber: "3"},					},				},			},		},	}	p := templates.NewParser()	re, err := p.Parsefile("example/index.HTML", d2)	if err != nil {		fmt.Println(err)		return	}	fmt.Println(re.String())
// 正确的调用方式 (right){:ID}{!List:data}    {!List:users}        {!List:my_List}            {:a}        {/List}    {/List}{/List}// 正确的调用方式 (right){!List:users}    {!if ID==(1*1+1-1-1)}        man: {:user_name}    {;elseif ID+1==21}        women: {:user_name}    {;else}        {!List:my_List}            {:phone_number}        {/List}    {/if}{/List}// 错误的调用方式 (wrong){!List:users}    {!List:my_List}        {:a}    {/List}{/List}

将来会支持更多的函数或自定义函数调用:

传送门 https://github.com/pywee/gtpl









总结

以上是内存溢出为你收集整理的go语言模板引擎,gtpl使用介绍全部内容,希望文章能够帮你解决go语言模板引擎,gtpl使用介绍所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1232455.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存