一、四种模板方案的核心区别

方案 核心机制 类型安全 性能 组件化 学习成本 推荐度
html/template 运行时模板执行 ★★ ★★ ★★ ★★★★★ ★★★★
templ 编译为 Go 代码 ★★★★★ ★★★★★ ★★★★★ ★★★★ ★★★★★
Jet 模板引擎运行时执行 ★★★ ★★★ ★★★★ ★★★★ ★★★
quicktemplate 编译为 Go 代码 ★★★ ★★★★★ ★★★ ★★★ ★★★

如果是新建 Go SSR 项目,优先考虑 templ。

如果是已有大量模板的传统 Go 项目,继续使用 html/template 通常更加合理。

二、html/template:Go 官方标准方案

html/template 是 Go 标准库的一部分,不需要第三方依赖。

tmpl := template.Must(
    template.ParseFiles("index.html"),
)

tmpl.Execute(w, data)

HTML 模板:

<h1>{{.Title}}</h1>

{{if .IsLogin}}
    <span>已登录</span>
{{end}}

{{range .Products}}
    <div>{{.Name}}</div>
{{end}}

2.1 工作方式

大致流程如下:

HTML 模板
    ↓
Parse
    ↓
模板内部结构
    ↓
Execute
    ↓
HTML

模板需要在运行时进行执行。

它需要处理:

  • 变量
  • 条件
  • 循环
  • 模板嵌套
  • 函数调用
  • HTML escaping
  • 上下文相关的安全处理

因此相比直接生成 Go 代码,会产生更多运行时开销。

三、templ:把 HTML 直接变成 Go 代码

templ 最大的区别是:

模板不是运行时解释执行,而是提前生成 Go 代码。

例如:

templ User(name string) {
    <div>
        <h1>Hello { name }</h1>
    </div>
}

执行:

templ generate

之后生成 Go 代码,再通过 Go 编译器进行编译。

整体流程:

.templ
   ↓
templ generate
   ↓
Go 代码
   ↓
go build
   ↓
最终二进制
   ↓
运行时直接执行 Go 代码

因此运行时不需要再解释模板语法。

四、templ 为什么性能更高?

传统模板的执行过程大致是:

请求
 ↓
模板执行
 ↓
解析模板节点
 ↓
处理变量
 ↓
处理条件
 ↓
HTML escaping
 ↓
输出

templ 更接近:

请求
 ↓
执行已经编译好的 Go 代码
 ↓
输出 HTML

因此 templ 的运行时工作更少。

典型 benchmark 中,templ 的渲染速度可以达到 html/template 的数倍,同时内存分配次数也明显减少。

但不能简单理解为 templ 永远比 html/template 快固定的 5 倍或 10 倍。

实际性能取决于:

  • HTML 复杂程度
  • 数据量
  • 循环数量
  • 函数调用
  • HTML escaping
  • ResponseWriter
  • 网络传输
  • 数据库查询

对于大多数 Web 应用而言,模板渲染通常并不是整个请求的主要耗时。

五、templ 最大优势其实不是性能

templ 真正有价值的地方是:

Go 类型系统 + HTML 组件化。

例如:

templ ProductCard(product Product) {
    <article class="product-card">
        <img src={ product.Image }>
        <h3>{ product.Name }</h3>
        <span>{ product.Price }</span>
    </article>
}

调用:

templ ProductList(products []Product) {
    <div>
        for _, product := range products {
            @ProductCard(product)
        }
    </div>
}

这里的 ProductCard 是一个真正的 Go 类型安全组件。

如果传入错误的数据类型,编译阶段就可以发现问题。

六、html/template 的类型安全较弱

例如:

<h1>{{.Name}}</h1>

Go 代码:

type User struct {
    Username string
}

模板实际上访问的是不存在的 .Name。很多问题需要到运行时才暴露。

而 templ:

<h1>{ user.Name }</h1>

本质上就是 Go 代码的一部分。

因此:

html/template
    ↓
模板
    ↓
运行时发现问题

而 templ:

templ
    ↓
生成 Go
    ↓
Go 编译器检查
    ↓
编译失败

对于大型项目,这个区别非常重要。

七、组件化能力对比

传统 html/template 通常通过模板调用实现复用:

{{template "header" .}}

大型项目容易逐渐形成:

templates/
├── layout.html
├── header.html
├── footer.html
├── product.html
├── product-list.html
└── user.html

随着项目增长,模板之间的数据依赖关系可能越来越难维护。

templ 更接近现代前端组件:

components/
├── Header.templ
├── Footer.templ
├── Navbar.templ
├── ProductCard.templ
├── Pagination.templ
└── Modal.templ

组件直接定义参数:

templ ProductCard(product Product) {
    ...
}

调用:

@ProductCard(product)

组件依赖关系更加明确。

八、Jet:传统模板引擎路线

Jet 属于典型的 Go 模板引擎。

使用方式更接近:

HTML
+
模板语法
+
模板引擎

相比 html/template,Jet 提供了更多模板层面的能力,例如:

  • 模板继承
  • 更丰富的模板语法
  • 更灵活的控制结构
  • 模板复用

因此如果团队非常习惯传统模板引擎,Jet 的开发体验可能比标准库模板更加丰富。

但是它仍然属于模板引擎路线,与 templ 的编译型方案存在明显区别。

九、quicktemplate:极致性能路线

quicktemplate 的设计目标非常明确:

尽可能降低模板渲染开销。

它同样采用代码生成思路,把模板转换成 Go 代码。

quicktemplate
       ↓
生成 Go 代码
       ↓
Go 编译
       ↓
运行

在特定 benchmark 中,它可以比传统 html/template 快很多。

但是性能并不是唯一指标。

quicktemplate 的主要取舍包括:

  • 生态相对较小
  • 开发体验不如现代组件化方案
  • 类型安全和组件组织体验不如 templ
  • 模板语法和普通 HTML、Go 的融合程度不如 templ

因此,如果单纯追求极限模板渲染性能,可以考虑 quicktemplate;如果追求综合开发体验,templ 更合适。

十、四种方案的性能思路

html/template
      │
      │ 运行时模板执行
      ↓
    中等性能


Jet
      │
      │ 运行时模板执行
      ↓
    中等性能


templ
      │
      │ 编译为 Go
      ↓
    高性能


quicktemplate
      │
      │ 编译为 Go + 性能优化
      ↓
    极高性能

但是实际 Web 请求通常包含:

HTTP 请求
   ↓
Router
   ↓
Middleware
   ↓
权限验证
   ↓
Redis
   ↓
数据库
   ↓
业务逻辑
   ↓
模板渲染
   ↓
网络传输

模板往往只是其中很小的一部分。

因此,不应该仅仅为了 benchmark 中的几倍性能,就重构整个模板系统。

十一、安全性对比

安全性是选择模板方案时比性能更加重要的一项。

11.1 html/template

Go 官方标准库重点解决了 HTML 上下文安全问题。

例如:

<div>{{.Content}}</div>

用户输入:

<script>alert('XSS')</script>

不会直接作为 HTML 执行。

11.2 templ

templ 同样提供 HTML escaping,并且通过生成 Go 代码实现渲染。

正确使用 templ 时,同样可以避免常见的 XSS 风险。

11.3 不要为了性能直接拼接 HTML

fmt.Fprintf(w, "<h1>%s</h1>", user.Name)

如果 user.Name 是用户输入,就可能产生 XSS。

正确原则是:

用户输入
 ↓
安全处理
 ↓
模板安全输出

而不是:

用户输入
 ↓
字符串拼接
 ↓
HTML

十二、templ 与 html/template 可以混用

不需要因为采用 templ 就一次性重构整个项目。

对于旧项目,可以采用:

现有系统
│
├── html/template
│     ├── 老页面
│     └── 老组件
│
└── templ
      ├── 新页面
      └── 新组件

逐步迁移。

这对于已经存在大量 HTML 模板的项目尤其重要。

十三、SEO 方面谁更好?

如果都是服务端直接输出完整 HTML:

搜索引擎
    ↓
完整 HTML
    ↓
SEO

那么 templ、html/template、Jet、quicktemplate 本身没有本质 SEO 差距。

SEO 的关键在于:

  • 是否 SSR
  • HTML 是否完整
  • Title
  • Description
  • Canonical
  • Structured Data
  • 页面内容
  • 内链
  • URL
  • 页面速度
  • Core Web Vitals

而不是模板引擎本身。

十四、与 HTMX 搭配

templ 非常适合:

Go
+
templ
+
HTMX

例如访问商品页面:

浏览器
   ↓
GET /products
   ↓
Go
   ↓
templ
   ↓
完整 HTML

用户点击分页或筛选:

浏览器
   ↓
HTMX
   ↓
GET /products?page=2
   ↓
Go
   ↓
templ
   ↓
HTML Fragment
   ↓
局部更新

这样可以避免引入大型 SPA 框架。

对于后台系统、电商网站、内容网站、社区、搜索网站和 SaaS 都非常适合。

十五、推荐技术栈

如果从零开始开发一个现代 Go SSR 网站,可以考虑:

                    Browser
                       │
                       ↓
                    HTMX
                       │
                       ↓
              ┌────────────────┐
              │   Go Router    │
              └────────────────┘
                       │
                       ↓
                 Controller
                       │
                       ↓
                  Service
                       │
                       ↓
                Repository
                  /         \
                 ↓           ↓
           PostgreSQL       Redis
                 │
                 ↓
             ViewModel
                 │
                 ↓
               templ
                 │
                 ↓
                HTML

前端:

templ
HTMX
Alpine.js(可选)
Tailwind CSS(可选)

后端:

Go
Gin / Echo / net/http
PostgreSQL
Redis

这套架构可以在不使用 React、Next.js 的情况下实现完整的现代 SSR 网站。

十六、最终选型建议

新项目

推荐:

templ

主要原因:

  • 编译期检查
  • Go 类型安全
  • 性能高
  • 组件化好
  • IDE 支持好
  • 与 Go 生态融合度高
  • 适合 HTMX
  • 适合 SSR
  • 适合大型项目

已经使用 html/template 的项目

推荐继续使用。

除非已经遇到以下问题:

  • 模板维护困难
  • 类型错误频繁
  • 组件复用困难
  • 模板渲染成为实际性能瓶颈

否则没有必要为了性能整体迁移。

极端性能场景

可以考虑:

quicktemplate

适合对模板渲染本身进行极限优化的场景,但需要接受生态和开发体验上的取舍。

需要丰富模板语法

可以考虑:

Jet

但新项目通常没有足够强的理由优先选择它。

十七、一句话结论

场景 推荐
Go 官方标准、简单稳定 html/template
新建 Go SSR 网站 templ
大型 Go SSR 项目 templ
Go + HTMX templ
极致模板性能 quicktemplate
传统模板引擎需求 Jet
已有大量 html/template 继续使用
为了性能从 html/template 全量迁移 不建议

综合建议:

2026 年新建 Go SSR 项目
        ↓
      templ
        ↓
Go + templ + HTMX
        ↓
类型安全 + 组件化 + 高性能 + SSR

最终结论:2026 年新建 Go SSR 项目,优先选择 templ;传统项目继续使用 html/template;只有明确存在模板渲染性能瓶颈时,才考虑为了性能迁移或使用 quicktemplate。