您的位置:首页 > 游戏 > 手游 > golang template HTML动态模板解析实现

golang template HTML动态模板解析实现

2024/10/6 5:54:03 来源:https://blog.csdn.net/tekin_cn/article/details/140059682  浏览:    关键词:golang template HTML动态模板解析实现

使用场景: 我们希望在模板里面动态解析指定的模板文件。

这个似乎使用go语言的模板嵌套 template 可以实现,不过模板嵌套声明里面是不支持使用变量的, 如:{{template "模板文件名" .}}  这里的"模板文件名"不能使用变量,原因我们另外分析, 所以只能是静态嵌套其他模板,不能实现动态嵌套其他模板!

golang动态模板解析实现思路

       要实现模板文件的动态解析, 我们可以通过在自定义模板函数的方式来实现。即 这个函数接收一个 模板文件变量 和模板解析参数 然后将模板文件解析为 HTML后返回给调用模板,这样就实现了模板的动态解析。 【ps: 如果你有更好的思路,欢迎反馈分享 :)】

        

golang HTML动态模板解析实现代码 示例

package mainimport ("bytes""html/template""path/filepath""github.com/spf13/viper" // 配置信息解析,可以使用其他你喜欢的
)// 获取所有自定义模板函数
func GetFuncs() template.FuncMap {// fmap map[string]anyreturn template.FuncMap{"TplInclude":  TplInclude,}
}// 动态模板解析函数 将指定的模板文件渲染为html内容后返回
//
//	tplFile 模板文件 这个可以是相对exe所在文件夹的路径 或者绝对路径
//	datas 可选参数  要应用到模板文件中的数据 通常为map格式
//
// 返回可直接渲染页面的 template.HTML 格式的字符串
// @author: TekinTian <tekinTian@gmail.com>
// @see https://dev.tekin.cn
func TplInclude(tplFile string, datas ...interface{}) template.HTML {var data interface{} // 应用到模板中的数据,默认空if len(datas) > 0 {data = datas[0] // 从可选参数中获取}// 从配置文件中获取分隔符delss := viper.GetStringSlice("viewer.delimiters")if len(delss) != 2 {delss = []string{"", ""} // 使用默认的分隔符,这里留空go最后解析的时候就会使用默认的分隔符 {{ }} 详情src/text/template/parse/lex.go}// 获取*template.Template对象 注意如果用到了自定义分隔符,自定义函数,则需要再这里重新注册t := template.New(tplFile).Delims(delss[0], delss[1]).Funcs(GetFuncs())// 解析模板文件 注意这里的模板文件路径必须是相对于exe运行文件所在的路径 或者 绝对路径tpl, err := t.ParseFiles(filepath.Join("templates", tplFile))if err != nil {return template.HTML(err.Error())}// 新建一个字符串缓存 writer, 解析后的模板内容将写入到这里// 这里如果是直接输出到浏览器的话用浏览器的writer即可, gin的输出writer为 c.Writer// 我们这里不直接输出到浏览器,而是输出到模板文件中,所以用这个自定义的writer接收后转为字符串输出到模板中.buf := bytes.NewBufferString("")// 渲染模板if err := tpl.Execute(buf, data); err == nil {return template.HTML(buf.String()) // 将缓存中的所有数据以html格式放回 注意必须是template.HTML格式 否则页面不会被解析} else {return template.HTML(err.Error())}
}

gin框架中使用示例

就是将我们自定义的函数通过 template.FuncMap方式加载到模板里面,特别提醒顺序,必须在r.LoadHTMLFiles函数之前,否则你的函数在模板里面生效!! 另外这里的模板加载,我们动态加载的模板在主r里面可以不用加载,只需要加载一个使用动态加载函数的模板就可以。

main.go

package mainimport ("fmt""html/template""net/http""time""github.com/gin-gonic/gin"
)func main() {r := gin.Default()// 就按照我们自定义的函数r.SetFuncMap(template.FuncMap{"TplInclude": TplInclude,})// 注意这里的模板加载 ,也可以是这样 r.LoadHTMLGlob("templates/*.html")r.LoadHTMLFiles("templates/index.html")r.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.hml", map[string]interface{}{"now": time.Now().Format(time.DateTime),"tpl": "xcontent.html", // 这里将要动态加载的模板作为变量传递给模板,然后在模板里面调用我们自定义的函数实现动态加载})})r.Run(":8080")
}

index.html示例

 {{TplInclude .tpl .}}   .tpl就是控制器里面传递来的变量参数, 最后一个 . 表示当前所有的变量信息。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>动态模板加载示例</title>
</head><body>普通变量调用示例:Now: {{ .now }} <br /><hr>调用我们自定义的模板函数, 传递2个参数 第一个.tpl是控制器传来的变量, 第二个.是当前的所有变量信息:<br />{{TplInclude .tpl .}}
</body></html>

xcontent.html 这个就是一个你自己定义的需要动态加载的模板文件,省略了。。。

总结

动态模板解析这里的关键点就是如何将指定的模板文件解析为HTML字符串,一般我们常见的就是直接将模板文件解析后输出到浏览器, 而这里是将模板文件解析后返回HTML格式的字符串,这就需要我们使用自定义的writer来接收模板解析后的内容,然后将这些内容返回, 注意这里在返回的时候必须使用 template.HTML 类型, 否则你返回的字符串将是被转码后的html,是不会被浏览器渲染的。

附 template包中定义的返回类型参考

我们上面就用到了下面的这个 HTML类型, 他其实就是一个string类型的类型定义, 当然如果我们希望实现动态渲染css,js 等其他内容,也需要使用下面定义的对应的类型才行哦。

package template// Strings of content from a trusted source.
type (// CSS encapsulates known safe content that matches any of://   1. The CSS3 stylesheet production, such as `p { color: purple }`.//   2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.//   3. CSS3 declaration productions, such as `color: red; margin: 2px`.//   4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.// See https://www.w3.org/TR/css3-syntax/#parsing and// https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.CSS string// HTML encapsulates a known safe HTML document fragment.// It should not be used for HTML from a third-party, or HTML with// unclosed tags or comments. The outputs of a sound HTML sanitizer// and a template escaped by this package are fine for use with HTML.//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.HTML string// HTMLAttr encapsulates an HTML attribute from a trusted source,// for example, ` dir="ltr"`.//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.HTMLAttr string// JS encapsulates a known safe EcmaScript5 Expression, for example,// `(x + y * z())`.// Template authors are responsible for ensuring that typed expressions// do not break the intended precedence and that there is no// statement/expression ambiguity as when passing an expression like// "{ foo: bar() }\n['foo']()", which is both a valid Expression and a// valid Program with a very different meaning.//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.//// Using JS to include valid but untrusted JSON is not safe.// A safe alternative is to parse the JSON with json.Unmarshal and then// pass the resultant object into the template, where it will be// converted to sanitized JSON when presented in a JavaScript context.JS string// JSStr encapsulates a sequence of characters meant to be embedded// between quotes in a JavaScript expression.// The string must match a series of StringCharacters://   StringCharacter :: SourceCharacter but not `\` or LineTerminator//                    | EscapeSequence// Note that LineContinuations are not allowed.// JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.JSStr string// URL encapsulates a known safe URL or URL substring (see RFC 3986).// A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`// from a trusted source should go in the page, but by default dynamic// `javascript:` URLs are filtered out since they are a frequently// exploited injection vector.//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.URL string// Srcset encapsulates a known safe srcset attribute// (see https://w3c.github.io/html/semantics-embedded-content.html#element-attrdef-img-srcset).//// Use of this type presents a security risk:// the encapsulated content should come from a trusted source,// as it will be included verbatim in the template output.Srcset string
)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com