必须先注册自定义truncate函数,再在模板中调用;注册需在loadhtmlglob之后、run之前,通过r.setfuncmap()传入gin.funcmap,函数签名为func(string, int) string,原文长度≤指定长度时原样返回。

模板中用 {{ . | truncate 50 }} 实现基础截断
Gin 默认不提供 truncate 模板函数,直接写 {{ . | truncate 50 }} 会报错 template: ...: function "truncate" not defined。必须先注册自定义函数,再在模板里调用。Gin 的 html/template 引擎只认你显式注册的函数,不会自动带任何文本处理工具。
注册 truncate 函数要传入 *template.Template
注册时机必须在 r.LoadHTMLGlob(...) 或 r.LoadHTMLFiles(...) 之后、r.Run() 之前;且要通过 r.SetFuncMap() 把函数挂到引擎上,不能只改全局 template.FuncMap —— Gin 不读那个。
-
r.SetFuncMap()接收的是gin.FuncMap类型(本质是map[string]interface{}),键是模板里用的名字,值是函数本身 - 函数签名推荐用
func(string, int) string,接收原文和最大长度,返回截断后字符串(含省略号) - 注意:如果原文长度 ≤ 指定长度,应原样返回,避免多加省略号
示例注册逻辑:
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.SetFuncMap(gin.FuncMap{
"truncate": func(s string, n int) string {
if len(s)
<h3>模板里调用时注意参数顺序和类型</h3>
<p><code>{{ .Content | truncate 100 }}</code> 是正确写法;<code>{{ truncate .Content 100 }}</code> 会报错 —— Go 模板只支持管道语法调用函数,不支持括号调用。另外,传入值必须是 <code>string</code> 类型,如果字段是 <code>interface{}</code> 或结构体字段,需提前确保可转为字符串,否则运行时报 <code>can't apply field selector</code> 或空字符串。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2602" title="Gin框架 1.9.0"><img
src="https://img.php.cn/upload/manual/001/589/237/6a731f5b72949207.png" alt="Gin框架 1.9.0" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2602" title="Gin框架 1.9.0" class="overflowclass">Gin框架 1.9.0</a>
<p class="overflowclass">Gin框架 1.9.0版本源码包下载,版本号 1.9.0,适合需要 sonic JSON 支持、路由修复和内容协商改进的 Go Web 开发场景。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2602" title="Gin框架 1.9.0" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 常见踩坑:前端传来的 JSON 字段如
"desc": null,后端用gin.H{"desc": nil}传入模板,{{ .desc | truncate 50 }}会静默输出空串,不报错也不提示 - 安全做法:在 handler 中预处理,比如
desc := "",再赋值;或函数内部加if s == nil { return "" }判断(此时函数签名需改为func(interface{}, int) string)
中文截断要按 rune 数而非字节长度
上面示例用 len(s) 是按字节算的,对中文会出错:一个汉字占 3 字节,len("你好") == 6,设 n=4 就可能切在 UTF-8 中间,渲染出 符号。真正该用 utf8.RuneCountInString(s)。
修正后的函数:
import "unicode/utf8"
// ...
"truncate": func(s string, n int) string {
r := []rune(s)
if len(r)
<p>这是最容易被忽略的一点:开发时用英文测试没问题,一上生产遇到中文就乱码,但错误不抛在 Gin 日志里,只体现在页面上,排查成本高。</p>










