https://github.com/OblivionOcean/Goh

Goh 是一款Go语言的预编译快速模板引擎。

English | 简体中文

目录

特性

  • 预编译模板引擎,提升运行速度。
  • 几乎兼容·Go语言的语法。
  • 0依赖。
  • 更改模板文件后自动重新编译。

性能测试

https://github.com/slinso/goTemplateBenchmark 获取,目前为本地测试结果,代码与Hero部分的测试代码相同,BenchmarkComplexGoDirectBuffer和BenchmarkComplexGoStaticString分别是写入Buffer和静态String,所以不做计算,因此复杂模板测试排名第一

goos: windows
goarch: amd64
pkg: github.com/SlinSo/goTemplateBenchmark
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
# 复杂模板测试
BenchmarkComplexGolang-16 36800 31428 ns/op 6562 B/op 290 allocs/op
BenchmarkComplexGolangText-16 88148 13370 ns/op 2235 B/op 107 allocs/op
BenchmarkComplexEgo-16 486294 2411 ns/op 568 B/op 31 allocs/op
BenchmarkComplexQuicktemplate-16 1367928 878.1 ns/op 0 B/op 0 allocs/op
BenchmarkComplexTempl-16 788673 1400 ns/op 408 B/op 11 allocs/op
BenchmarkComplexFtmpl-16 293755 3982 ns/op 3534 B/op 38 allocs/op
BenchmarkComplexFtmplInclude-16 317361 4142 ns/op 3534 B/op 38 allocs/op
BenchmarkComplexMustache-16 90567 13748 ns/op 7274 B/op 156 allocs/op
BenchmarkComplexGorazor-16 361304 3195 ns/op 3688 B/op 24 allocs/op
BenchmarkComplexJetHTML-16 189176 5928 ns/op 532 B/op 5 allocs/op
BenchmarkComplexHero-16 1410391 863.5 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoh-16 2304783 535.4 ns/op 0 B/op 0 allocs/op
BenchmarkComplexJade-16 1826784 651.8 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoDirectBuffer-16 2890996 414.6 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoHyperscript-16 1717754 778.6 ns/op 0 B/op 0 allocs/op
BenchmarkComplexGoStaticString-16 84003024 14.44 ns/op 0 B/op 0 allocs/op
# 简单模板测试
BenchmarkGolang-16 300493 3691 ns/op 768 B/op 35 allocs/op
BenchmarkGolangText-16 1000000 1073 ns/op 128 B/op 7 allocs/op
BenchmarkGoDirectBuffer-16 21959280 55.81 ns/op 0 B/op 0 allocs/op
BenchmarkGoCustomHtmlAPI-16 14034298 85.06 ns/op 0 B/op 0 allocs/op
BenchmarkGoFunc3-16 14962965 68.62 ns/op 0 B/op 0 allocs/op
BenchmarkEgo-16 2577276 464.3 ns/op 85 B/op 8 allocs/op
BenchmarkHB-16 280617 4445 ns/op 2448 B/op 51 allocs/op
BenchmarkQuicktemplate-16 7013572 168.9 ns/op 0 B/op 0 allocs/op
BenchmarkFtmpl-16 1000000 1000 ns/op 774 B/op 12 allocs/op
BenchmarkAce-16 179811 6605 ns/op 1121 B/op 40 allocs/op
BenchmarkAmber-16 268149 3800 ns/op 849 B/op 36 allocs/op
BenchmarkMustache-16 523143 2636 ns/op 1722 B/op 30 allocs/op
BenchmarkPongo2-16 350612 3862 ns/op 2074 B/op 32 allocs/op
BenchmarkHandlebars-16 162860 7261 ns/op 3423 B/op 75 allocs/op
BenchmarkGorazor-16 1562088 772.3 ns/op 512 B/op 5 allocs/op
BenchmarkSoy-16 639549 2200 ns/op 1224 B/op 19 allocs/op
BenchmarkJetHTML-16 1960117 600.4 ns/op 0 B/op 0 allocs/op
BenchmarkHero-16 10452396 113.9 ns/op 0 B/op 0 allocs/op
BenchmarkGoh-16 14838537 81.97 ns/op 0 B/op 0 allocs/op
BenchmarkJade-16 15025261 78.85 ns/op 0 B/op 0 allocs/op
BenchmarkTempl-16 4015622 293.1 ns/op 96 B/op 2 allocs/op
BenchmarkGomponents-16 479330 2882 ns/op 1112 B/op 56 allocs/op
ok github.com/SlinSo/goTemplateBenchmark 65.553s

安装

go get -u github.com/OblivionOcean/Goh
go install github.com/OblivionOcean/Goh # 依赖
go get golang.org/x/tools/cmd/goimports
go install golang.org/x/tools/cmd/goimports

使用

~ $ Goh
Usage of ./Goh:
-dest string
generated golang files dir, it will be the same with source if not set
-ext string
source file extensions, comma splitted if many (default ".html")
-pkg string
the generated template package name, default is template (default "template")
-src string
the html template file or directory (default "./")

完整的使用方法请参考实例程序

<%: func UserList(title string, userList []string, buf *bytes.Buffer) %>
<!DOCTYPE html>
<html> <head>
<title>
<%= title %>
</title>
</head> <body>
<h1>
<%= title %>
</h1>
<ul>
<% for _, user :=range userList { %>
<% if user !="Alice" { %>
<li>
<%= user %>
</li>
<% } %>
<% } %>
</ul>
</body> </html>
package main

import (
"bytes"
"net/http" "github.com/OblivionOcean/Goh/example/template"
) func main() {
http.HandleFunc("/users", func(w http.ResponseWriter, req *http.Request) {
var userList = []string{
"Alice",
"Bob",
"Tom",
} buffer := new(bytes.Buffer)
template.UserList("User List", userList, buffer) w.Write(buffer.Bytes())
}) http.ListenAndServe(":8080", nil)
}

语法

文档修改自https://github.com/shiyanhui/hero

Goh总共有九种语句,他们分别是:

  • 函数定义语句 <%: func define %>

    • 该语句定义了该模板所对应的函数,如果一个模板中没有函数定义语句,那么最终结果不会生成对应的函数。
    • 该函数最后一个参数必须为*bytes.Buffer或者io.Writer, hero会自动识别该参数的名字,并把把结果写到该参数里。
    • 例:
      • <%: func UserList(userList []string, buffer *bytes.Buffer) %>
      • <%: func UserList(userList []string, w io.Writer) %>
      • <%: func UserList(userList []string, w io.Writer) (int, error) %>
  • 模板继承语句 <%~ "parent template" %>
    • 该语句声明要继承的模板。
    • 例: <%~ "index.html" >
  • 模板include语句 <%+ "sub template" %>
    • 该语句把要include的模板加载进该模板,工作原理和C++中的#include有点类似。
    • 例: <%+ "user.html" >
  • 包导入语句 <%! go code %>
    • 该语句用来声明所有在函数外的代码,包括依赖包导入、全局变量、const等。
  • 该语句不会被子模板所继承
  • 例:
    <%!
import (
"fmt"
"strings"
) var a int const b = "hello, world" func Add(a, b int) int {
return a + b
} type S struct {
Name string
} func (s S) String() string {
return s.Name
}
%>
  • 块语句 <%@ blockName { %> <% } %>

暂不支持该语法,请使用其他方式代替。

  • Go代码语句 <% go code %>
  • 该语句定义了函数内部的代码部分。
  • 例:
<% for _, user := range userList { %>
<% if user != "Alice" { %>
<%= user %>
<% } %>
<% } %> <%
a, b := 1, 2
c := Add(a, b)
%>
  • 原生值语句 <%==[t] variable %><%- variable %>
  • 该语句把变量转换为string。
  • t是变量的类型,hero会自动根据t来选择转换函数。t的待选值有:
  • b: bool
  • i: int, int8, int16, int32, int64
  • u: byte, uint, uint8, uint16, uint32, uint64
  • f: float32, float64
  • s: string
  • bs: []byte
  • v: interface

注意:

  • 如果t没有设置,那么t默认为s.
  • 最好不要使用v,因为其对应的转换函数为fmt.Sprintf("%v", variable),该函数很慢。
  • 例:
<%== "hello" %>
<%==i 34 %>
<%==u Add(a, b) %>
<%==s user.Name %>
  • 转义值语句 <%= statement %>
  • 该语句把变量转换为string后,又通过html.EscapesString记性转义。
  • t跟上面原生值语句中的t一样。
  • 例:
<%= a %>
<%= a + b %>
<%= Add(a, b) %>
<%= user.Name %>
  • 注释语句 <%# note %>
  • 该语句注释相关模板,注释不会被生成到go代码里边去。
  • 例: <# 这是一个注释 >.

感谢

Shiyanhui/hero

Goh:一款Go语言的预编译快速模板引擎。(Benchmark排名第一)的更多相关文章

  1. Jquery 模板插件 jquery.tmpl.js 的使用方法(2):嵌套each循环,temp调用(使用预编译的模板缓存)

    直接上代码吧 一:主窗口 /*#region SendChooseTargetTemplate 发送候选人主窗口模板*/ var SendChooseTargetTemplate = ''; Send ...

  2. 热重载 预编译 编译器 JS引擎 作用域

    热重载就是页面每次改动,不需要手动去刷新,可自动刷新.保持vuex的状态. JS之预编译 JavaScript的预编译 编译器 JS引擎 作用域三者之间的关系 建议你先去看看你不知道的JavaScri ...

  3. 聊聊C语言的预编译指令include

    "include"相信大家不会陌生,在我们写代码时,开头总会来一句"include XXX".include是干嘛用的,很多教材都提到了,因此这里不会再详细解释 ...

  4. C语言的预编译

    由"源代码"到"可执行文件"的过程包括四个步骤:预编译.编译.汇编.链接.所以,首先就应该清楚的首要问题就是:预编译只是对程序的文本起作用,换句话说就是,预编译 ...

  5. javaScript语言的预编译与运行

    JS代码执行的过程: 1.预编译 ---- 事先对js代码做一个预处理 2.代码运行---开始执行JS代码. JS编程: 1.加载DOM的最好在/BODY之前 2.与DOM渲染无关的放在Head里面 ...

  6. C语言的预编译,程序员必须懂的知识!【预编译指令】【预编译过程】

    由“源代码”到“可执行文件”的过程包括四个步骤:预编译.编译.汇编.链接.所以,首先就应该清楚的首要问题就是:预编译只是对程序的文本起作用,换句话说就是,预编译阶段仅仅对源代码的单词进行变换,而不是对 ...

  7. cocos 3.16 生成预编译库模板

    打开模板功能 不知道什么原因,cocos 3.16关闭了模板功能,因此使用cocos -h命令时,无法显示gen-templates参数. 打开的方式也挺简单,打开tools/cocos2d-cons ...

  8. (十八)C语言之预编译命令、宏

  9. iOS中的预编译指令的初步探究

    目录 文件包含 #include #include_next #import 宏定义 #define #undef 条件编译 #if #else #endif #if define #ifdef #i ...

  10. [代码审计基础 02]-SQL注入和预编译和预编译绕过

    SQL注入 thinkphp基本没得SQL注入,除非魔改 ORM框架的错误使用 一个专门用来防御SQL注入的框架 错误写法-java/mybatis <select id = "fin ...

随机推荐

  1. golang之json.RawMessage

    RawMessage 具体来讲是 json 库中定义的一个类型.它实现了 Marshaler 接口以及 Unmarshaler 接口,以此来支持序列化的能力.注意上面我们引用 官方 doc 的说明. ...

  2. 在Python工具箱中,创建对应子工具集

    目录 问题描述 实现方法 问题描述 在Pro中,新建自定义工具箱后,直接通过操作可以添加工具集. 但是新建python工具箱后,却没有新建的操作.因为python工具箱的对象定义,都是在脚本中定义的, ...

  3. 论文解读《From Generation to Judgment: Opportunities and Challenges of LLM-as-a-judge》

    发表时间:2024 期刊会议:arxiv 论文单位:Arizona State University 论文作者:Dawei Li, Bohan Jiang, Liangjie Huang, Alimo ...

  4. 拥抱云原生,数据湖加速器 GooseFS 助力 Fluid 数据缓存实现

    01 ​前言 数据湖加速器 GooseFS 是由腾讯云推出的高性能.高可用.弹性的分布式缓存方案.依靠对象存储(Cloud Object Storage,COS)作为数据湖存储底座的成本优势,为数据湖 ...

  5. 对象存储 COS 推出一站式内容审核服务,助力打造绿色互联网

    今年,国家网信办深入推进"清朗·春节网络环境"专项行动.截至3月24日,网信办共累计清理相关违法违规信息208万余条,处置账号7.2万余个,协调关闭.取消备案网站平台2300余家. ...

  6. HTMLDivElement.prototype

    HTMLDivElement.prototype.test = function(){console.log("i am div")} $0.innerHTML = '<di ...

  7. django生命周期流程图与django路由层

    目录 一.django请求生命周期流程图 二.django路由层 1.路由匹配 2.转换器 3.正则匹配 不同版本的区别 正则匹配斜杠导致的区别 4.正则匹配的无名有名分组 分组匹配 无名分组 有名分 ...

  8. JSchException: Algorithm negotiation fail问题解决之路

    最近一个需求用到了SFTP上传功能,同事之前已经封装好了SFTP工具类,用的是JSch,本着不要重复造轮子的想法,就直接拿来用了.交代下环境,JDK为1.7,JSch版本为0.1.51.自测通过.测试 ...

  9. Netty 那些事儿 ——— 关于 “Netty 发送大数据包时 触发写空闲超时” 的一些思考

    作者:tomas家的小拨浪鼓链接:https://www.jianshu.com/p/8fe70d313d78来源:简书 本文是笔者和朋友(笔名:oojeek)一起讨论该问题的一个记录.文章以讨论过程 ...

  10. Qt支持RKMPP硬解的视频监控系统/性能卓越界面精美/实时性好延迟低/录像存储和回放/云台控制

    一.前言 之前做的监控系统,已经实现了在windows上硬解码比如dxva2和d3d11va,后续又增加了linux上的硬解vdpau的支持,这几种方式都是跨系统的硬解实现方案,也是就是如果都是win ...