golang微服务框架中如何扩展go-mile米乐体育
golang微服务框架中如何扩展go-zero使之支持html模板解析自动化
本篇文章为大家展示了golang微服务框架中如何扩展go-zero使之支持html模板解析自动化,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
go-zero本身支持html模板解析,我们只需要添加url对应模板解hanlder,实现逻辑就可以了
但是winlion太懒了,我甚至想
不写任何一个和模板相关的handler
如果有新的模板,直接把模板到某个特定目录就好,不要动任何go代码
在开发环境下没有缓存,修改了模板文件无需重启
需求在这里,开撸吧
在代码开始前,你可能需要阅读
金光灿灿的gorm v2 适合创业的golang微服务框架go-zero实战 如果对go-zero已经了解,直接跳过吧
创建项目
生成go.mod文件
以如下指令创建项目
mkdirhtmlcdhtmlgomodinithtml
定义html.api
本文设计api如下 |描述|格式|方法|参数|返回|是否需要鉴权| |----|----|----|----|----|----| |用户登录|/open/authorization|post|mobile:手机号,passwd:密码,code:图片验证码|id:用户id,token:用户token|否|
根据以上描述,书写api的模板文件如下
type(useroptreqstruct{mobilestring`form:"mobile"`passwdstring`form:"passwd"`codestring`form:"code,optional"`}useroptrespstruct{iduint`json:"id"`tokenstring`json:"token"`})servicehtml-api{@server(handler:authorizationhandlerfolder:open)post/open/authorization(useroptreq)returns(useroptresp)}
注意
本文和html模板相关,可以不适用goctl工具
但是由于使用工具可以为我们节省很多搭建框架相关的工作,所以建议使用用ctl生成
生成代码
采用如下指令生成代码
goctlapigo-apihtml.api-dir.
此时用go run html.go
指令可以发现系统以及运行
html模板自动解析实现思路
模板解析需要了解如下俩个已知知识点
html网页输出本质上是get请求输出
相对于一个项目来说,模板文件个数是有限的,因此我们可以将模板枚举出来,完成访模板名称和请求之间的映射
对于第一个,我们可以构建get路由来实现请求,以mile米乐体育首页请求http://127.0.0.1:8888/index.html
为例,核心代码如下,
htmltplrouter:=rest.route{method:http.methodget,path:"/index.html",handler:htmlhandler(...),}engine.addroute(htmltplrouter)
在上述代码中,htmlhandler
函数实现了对请求的响应,也就是解析了模板并将模板内容输出
//gloabtemplate:全局解析的模板参数//tplname:模板名称,//serverctx应用配置funchtmlhandler(gloabtemplate*template.template,tplnamestring,serverctx*svc.servicecontext)http.handlerfunc{returnfunc(whttp.responsewriter,r*http.request){//模板名字就是r.url.patht:=gloabtemplate//如果是调试模式,则支持热解析ifserverctx.config.debug{t,_=template.new("").funcs(funcmap()).parseglob(serverctx.config.templatepattern)}err:=t.executetemplate(w,tplname,r.url.query())iferr!=nil{httpx.error(w,err)}}}
如何建立uri和模板名称之间的映射关系
这里有几个点需要强调:
在golang中,每个包含模板内容的html文件会被解析成一个模板,如在
view/www/
下新建test.html
文件,即使里面没有内容,系统也会将其解析得到一个名叫test.html
的模板。如果在模板文件以template标签中定义名称为
www/test.html
的模板,则系统又会解析得到一个名叫www/test.html
的模板,此时存在俩个模板,一个名叫test.html
,一个名叫www/test.html
view/www/test.html
文件内容如下
{{define"www/test.html"}}
这是模板www/test.html的内容
{{end}}因此我们可以取巧,将模板名称命名成需要建立映射关系的uri 比如外部通过http://127.0.0.1:8888/www/test.html
来访问,此时req.uri.path为/www/test.html
我们可以用这个作为模板名称
如何枚举模板
这里用到了parseglob
函数,这个函数本质上是对filepath.parseglob()
和template.parsefiles()
的封装,可以遍历满足一定格式的路径的所有文件,假设我们建立模板存放目录internal\view
如下
tree/f/a|go.mod|go.sum|html.api|html.go|readme.md| ---etc|html-api.yaml|\---internal ---config|config.go| ---handler||routes.go|||\---open|authorizationhandler.go| ---logic|\---open|authorizationlogic.go| ---svc|servicecontext.go| ---types|types.go|\---view ---public|footer.html|header.html|\---wwwindex.htmltest.html
则我们可以使用格式字符串 ./internal/view/**/*
来遍历并解析并解析模板,建立模板和uri之间的对应关系,核心代码如下
gloabtemplate,err:=template.new("").funcs(funcmap()).parseglob("./internal/view/**/*")//range轮询for_,tpl:=rangegloabtemplate.templates(){patern:=tpl.name()if!strings.hasprefix(patern,"/"){patern="/" patern}//mile米乐体育首页默认index.htmlindex.htmindex.phptplname:=tpl.name()if0==len(tplname){tplname=serverctx.config.templateindex}pagerouters=append(pagerouters,rest.route{method:http.methodget,path:patern,handler:htmlhandler(gloabtemplate,tplname,serverctx),})logx.infof("registerpage%s%s",patern,tplname)}//添加到engin路由中engine.addroutes(pagerouters)
如何在模板中使用函数
有时候我们需要在模板中使用函数,则需要用到函数映射功能,golang提供接口函数funcs()
来注入,
假设我们需要在/www/version.html中查看系统版本,应该怎么做呢?
定义相关函数
//handlers\funcs.gopackagehandlerimport("html/template")//定义varfuncsmaptemplate.funcmap=make(template.funcmap)funcfuncmap()template.funcmap{funcsmap["version"]=versionfuncsmap["hello"]=helloreturnfuncsmap}funcversion()string{//这个函数返回当前版本号0.0.1return"0.01"}funchello(strstring)string{//这个函数返回当前版本号0.0.1return"hello" str}
应用可以通过 template.new("").funcs(funcmap())
来注入响应函数
定义模板文件 新建文件
view/www/version.html
,内容如下
{{define"www/version.html"}}
当前版本号:{{version}}
这里测试带参数的函数:{{hello"word"}}
{{end}}无参数的函数展示 此时模板文件中通过
{{version}}
即可调用并显示版本号0.01有参数的函数 对应有参数的函数,按照参数顺序排列,中间用空格隔开
以上显示结果
当前版本号:0.01这里测试带参数的函数:helloword
如何模板嵌套
使用templete
指令进行嵌套
新建view/public/header.html
内容如下
这是head
新建view/public/footer.html
内容如下