Go 模板利器:Sprig 模板函数使用说明书

文章目录

Sprig 是一个为 Go 语言内置模板(text/templatehtml/template)提供超过 100 个常用模板函数的库。它的设计灵感来源于 Twig 和 JavaScript 库(如 underscore.js)中的模板函数。

Sprig 遵循的原则包括:使用模板函数进行格式化布局简单类型转换以及辅助处理常见格式化和布局需求的实用程序(例如算术运算)。所有函数通常以小写形式命名,以遵循 Go 模板惯例。

注意: 模板函数不应该返回错误,除非无法打印出合理的值。例如,字符串到整数的转换如果失败,通常会显示一个默认值,而不是产生错误。

本指南整合了 Sprig 中提供的关键功能(genericMap 中的函数),方便大家查询和学习。

Sprig 基础用法

Go 开发者可以将 Sprig 作为一个库导入,并通过 sprig.FuncMap() 加载其函数映射。

import (
    "github.com/Masterminds/sprig/v3"
    "html/template"
)

// 必须在加载模板之前设置 FuncMap
tpl := template.Must(template.New("base").Funcs(sprig.FuncMap()).ParseGlob("*.html"))

在模板内部,函数通常使用管道 (|) 调用,并且约定为小写。

{{ "hello!" | upper | repeat 5 }} // 结果:HELLO!HELLO!HELLO!HELLO!HELLO!

一、默认值、JSON 与流程控制函数

这些函数主要用于设置默认值、检查空值、以及处理 JSON 编码/解码。

函数名称功能描述用法示例
default为模板变量设置简单默认值。如果变量为空(如 0、""、[]、{}、false 或 nil),则返回默认值。default "foo" .Bar
empty检查给定值是否为空,返回 truefalseempty .Foo
coalesce接受一个值列表,返回列表中第一个非空值。coalesce .name .parent.name "Matt"
all接受一个值列表,所有值都非空时返回 trueall (eq .Method "POST") .Data
any接受一个值列表,任一值非空时返回 trueany 0 1 2
fromJson, mustFromJson将 JSON 文档解码为结构体。mustFromJson 在输入无效时返回错误。fromJson "{\"foo\": 55}"
toJson, mustToJson将项目编码为 JSON 字符串。mustToJson 编码失败时返回错误。toJson .Item
toPrettyJson, mustToPrettyJson将项目编码为美观(缩进)的 JSON 字符串。toPrettyJson .Item
toRawJson, mustToRawJson将项目编码为 JSON 字符串,且不转义 HTML 字符。toRawJson .Item
ternary三元运算符,如果测试值为 true,返回第一个值,否则返回第二个值。ternary "foo" "bar" true
fail无条件返回一个空字符串和指定的错误。fail "Please accept the agreement"

二、字典函数

Sprig 提供了 dict 类型(无序的键/值存储)及其操作函数。键必须是字符串。

函数名称功能描述用法示例
dict通过传递键值对列表来创建字典。$myDict := dict "k1" "v1" "k2" "v2"
get从字典中获取给定键的值。如果键未找到,返回 ""get $myDict "k1"
set向字典添加新的键/值对,会修改原字典$_ := set $myDict "k3" "v3"
unset从字典中删除给定键。$_ := unset $myDict "k3"
hasKey检查字典是否包含给定键。hasKey $myDict "k1"
pluck接受一个键和多个字典,返回所有匹配该键的值的列表。pluck "name" $d1 $d2
dig遍历嵌套字典,根据键列表查找值。如果路径中任一键未找到,返回提供的默认值。dig "user" "role" "humanName" "guest" $dict
merge, mustMerge合并两个或多个字典,以目标字典($dest)优先。这是一个深度合并操作。$newdict := merge $dest $source1
mergeOverwrite, mustMergeOverwrite合并字典,但优先级从右到左,会覆盖目标字典的值。$newdict := mergeOverwrite $dest $source1
keys返回一个或多个字典中所有键的列表(无序)。keys $myDic | sortAlpha
pick从字典中选择给定键,创建一个新字典。pick $myDict "name1" "name2"
omit返回一个新字典,包含所有匹配给定键的键。omit $myDict "name1" "name3"
values返回源字典中所有值的列表(无序,只支持一个字典)。$vals := values $myDict
deepCopy, mustDeepCopy对值(包括字典和其他结构)进行深度复制。dict "a" 1 "b" 2 | deepCopy

三、列表和切片函数

Sprig 的 list 类型设计为不可变,操作通常返回新列表。

函数名称功能描述用法示例
list创建一个列表。$myList := list 1 2 3 4 5
first, mustFirst获取列表的头部元素。first $myList
rest, mustRest获取列表的尾部(除第一个元素以外的所有内容)。rest $myList
last, mustLast获取列表的最后一个元素。last $myList
initial, mustInitial返回除最后一个元素以外的所有元素。initial $myList
append, mustAppend向列表追加新项,创建新列表。$new = append $myList 6
prepend, mustPrepend将元素推送到列表前面,创建新列表。prepend $myList 0
concat将任意数量的列表连接成一个新列表。concat $l1 $l2
reverse, mustReverse返回元素顺序颠倒的新列表。reverse $myList
uniq, mustUniq生成移除所有重复项的列表。list 1 1 2 | uniq
without, mustWithout从列表中过滤掉指定的项目。without $myList 1 3 5
has, mustHas测试列表是否包含特定元素。has 4 $myList
compact, mustCompact移除列表中具有空值("")的条目。$copy := compact $list
slice, mustSlice获取列表的部分元素,等同于 list[n:m] 切片操作。slice $myList 1 3
chunk将列表拆分成给定大小的块。chunk 3 (list 1 2 3 4 5 6 7 8)
join将字符串列表连接成单个字符串,使用给定分隔符。list "h" "w" | join "\_"
splitList将字符串分割成字符串列表。splitList "$" "f$b$z"
split将字符串分割成一个带有索引键的字典 (旧函数)。split "$" "f$b$z"
splitn将字符串分割成一个带有索引键的字典,并限制子字符串数量。splitn "$" 2 "f$b$z"
sortAlpha将字符串列表按字母顺序排序。list "c" "a" | sortAlpha
until构建一个从 0 开始的整数范围。until 5
untilStep构建一个整数范围,可定义开始、停止和步长。untilStep 3 6 2
seq类似于 bash 的 seq 命令,生成包含开始和结束的整数。seq 0 2 10

四、数学函数

Sprig 提供了整数 (int64) 和浮点数 (float64) 的数学操作。

函数名称类型功能描述用法示例
add, addf整数/浮点求和。add 1 2 3, addf 1.5 2
add1, add1f整数/浮点递增 1。add1 5
sub, subf整数/浮点减法。sub 5 2, subf 7.5 2 3
mul, mulf整数/浮点乘法。mul 1 2 3, mulf 1.5 2 2
div, divf整数/浮点除法。div 10 2, divf 10 2 4
mod整数模运算。mod 10 3
max, maxf整数/浮点返回系列中的最大值。max 1 2 3, maxf 1 2.5 3
min, minf整数/浮点返回系列中的最小值。min 1 2 3, minf 1.5 2 3
floor浮点返回小于或等于输入值的最大浮点值。floor 123.9999
ceil浮点返回大于或等于输入值的最小浮点值。ceil 123.001
round浮点将浮点值四舍五入到给定的小数位数。round 123.555555 3
randInt整数返回一个随机整数值(min 包含,max 不包含)。randInt 12 30

五、字符串操作函数

Sprig 提供了大量的字符串操作、格式化和正则表达式函数。

函数名称功能描述用法示例
trim移除字符串两侧的空格。trim " hello "
trimAll移除字符串前后给定的字符。trimAll "$" "$5.00"
trimSuffix仅移除后缀。trimSuffix "-" "hello-"
trimPrefix仅移除前缀。trimPrefix "-" "-hello"
upper, lower, title, untitle转换为大写/小写/标题大小写/移除标题大小写。upper "hello"
repeat重复字符串多次。repeat 3 "hello"
substr获取子字符串(开始索引, 结束索引, 字符串)。substr 0 5 "hello world"
nospace移除字符串中所有空格。nospace "hello w o r l d"
trunc截断字符串,不添加后缀。trunc 5 "hello world"
abbrev截断字符串并添加省略号 (...)。abbrev 5 "hello world"
abbrevboth截断字符串两端并添加省略号。abbrevboth 5 10 "1234 5678 9123"
initials提取多个单词的首字母并组合。initials "First Try"
randAlphaNum, randAlpha, randNumeric, randAscii生成不同字符集(数字/字母/两者/ASCII)的密码安全随机字符串。randNumeric 3
wrap, wrapWith在给定列数处换行 (wrap 使用 \n),wrapWith 允许指定换行符。wrap 80 $text
contains测试一个字符串是否包含在另一个字符串中。contains "cat" "catch"
hasPrefix, hasSuffix测试字符串是否具有给定前缀或后缀。hasPrefix "cat" "catch"
quote, squote用双引号 (quote) 或单引号 (squote) 包装字符串。quote "text"
cat连接多个字符串,用空格分隔。cat "h" "b" "w"
indent缩进给定字符串中的每一行。indent 4 $text
nindent类似于 indent,但在开头添加新行和缩进。nindent 4 $text
replace执行简单字符串替换。"I Am Henry VIII" | replace " " "-"
plural根据长度整数使字符串复数化。len $fish | plural "one" "many"
snakecase, camelcase, kebabcase字符串大小写格式转换(下划线/驼峰/Kebab-case)。snakecase "FirstName"
swapcase交换字符串的大小写(基于单词的算法)。swapcase "This Is A.Test"
shuffle打乱字符串中的字符顺序。shuffle "hello"
regexMatch, mustRegexMatch检查字符串是否包含正则表达式匹配。regexMatch "^[A-Z]" "a"
regexFindAll, mustRegexFindAll返回所有正则表达式匹配的切片。regexFindAll "" "123456789" -1
regexReplaceAll, mustRegexReplaceAll替换正则表达式匹配项(支持 $1 展开)。regexReplaceAll "a(x*)b" "-ab-" "${1}W"
regexQuoteMeta转义正则表达式元字符。regexQuoteMeta "1.2.3"

六、日期函数

用于处理时间、日期格式化和持续时间。

函数名称功能描述用法示例
now返回当前日期/时间。
ago返回自 time.Now 起经过的持续时间(秒级分辨率)。ago .CreatedAt
date格式化日期。Go 的日期格式化基于特定基准日期 Mon Jan 2 15:04:05 MST 2006now | date "2006-01-02"
dateInZone格式化日期,并带有时区。dateInZone "2006-01-02" (now) "UTC"
duration将给定秒数格式化为 time.Duration 字符串。duration "95"
durationRound将给定持续时间四舍五入到最显著的单位。durationRound "2h10m5s"
unixEpoch返回 time.Time 距离 Unix 纪元以来的秒数。now | unixEpoch
dateModify, mustDateModify接受修改量(如 “+1h”)和日期,返回修改后的时间戳。mustDateModify 错误时返回错误。now | date_modify "-1.5h"
htmlDate, htmlDateInZone格式化日期,用于 HTML 日期选择器输入字段(htmlDateInZone 带时区)。now | htmlDate
toDate, mustToDate将字符串转换为日期。mustToDate 转换失败时返回错误。toDate "2006-01-02" "2017-12-31"

七、加密和安全函数

提供了多种哈希计算、密码派生和证书生成功能。

函数名称功能描述用法示例
sha1sum, sha256sum, sha512sum计算字符串的 SHA1/SHA256/SHA512 摘要。SHA256/512 返回“ASCII armored”格式。sha256sum "Hello world!"
adler32sum计算字符串的 Adler-32 校验和。adler32sum "Hello world!"
bcrypt生成字符串的 bcrypt 散列。bcrypt "myPassword"
htpasswd生成 Apache HTTP Server 基础认证所需的 htpasswd 格式散列。htpasswd "user" "pass" "sha"
randBytes生成 N 个密码安全的随机字节序列,返回 base64 编码字符串。randBytes 24
derivePassword基于共享的“主密码”约束派生特定密码。derivePassword 1 "long" "pass" "user" "example.com"
genPrivateKey生成编码为 PEM 块的新私钥(支持 ecdsa, dsa, rsa, ed25519)。genPrivateKey "rsa"
genCA使用 2048 位 RSA 私钥生成自签名 x509 CA 证书。$ca := genCA "foo-ca" 365
genCAWithKey使用给定私钥生成自签名 x509 CA 证书。$ca := genCAWithKey "cn" 365 (genPrivateKey "rsa")
genSelfSignedCert, genSelfSignedCertWithKey使用 RSA 或给定私钥生成自签名 x509 证书。$cert := genSelfSignedCert "foo.com" nil nil 365
genSignedCert, genSignedCertWithKey使用 CA 签署新的 x509 证书(使用 RSA 或给定私钥)。$cert := genSignedCert "foo.com" nil nil 365 $ca
buildCustomCert通过 base64 编码的证书和私钥构建证书对象。$ca := buildCustomCert "crt" "key"
encryptAES使用 AES-256 CBC 加密文本,返回 base64 编码字符串。encryptAES "key" "plaintext"
decryptAES解密 base64 编码的 AES-256 CBC 字符串。"b64string" | decryptAES "key"

八、其他高级功能

类别函数名称功能描述用法示例
类型转换atoi, float64, int, int64, toString将字符串转换为整数;将值转换为指定类型。atoi "123", int64 5.5
类型转换toDecimal将 Unix 八进制权限转换为十进制 int64"0777" | toDecimal
类型转换toStrings将列表或切片转换为字符串列表。list 1 2 3 | toStrings
编码b64enc, b64decBase64 编码或解码。
编码b32enc, b32decBase32 编码或解码。
UUIDuuidv4生成 UUID v4(随机生成)。uuidv4
网络getHostByName接收域名并返回 IP 地址。getHostByName "google.com"
URLurlParse解析 URL 字符串并生成包含 URL 各部分的字典。urlParse "http://..."
URLurlJoin连接字典(URL 部分)以生成 URL 字符串。urlJoin (dict "scheme" "http" ...)
OS (注意安全)env, expandenvenv 读取环境变量;expandenv 替换字符串中的环境变量。env "HOME", expandenv "$PATH"
路径base, dir, clean, ext, isAbs路径操作,使用 / 分隔符。base "foo/bar/baz"
文件路径osBase, osDir, osClean, osExt, osIsAbs文件路径操作,使用操作系统特定的路径分隔符 (os.PathSeparator)。osBase "/foo/bar/baz"
反射kindOf, kindIs返回或检查对象的 Go Kind(如 stringslice)。kindOf "hello"
反射typeOf, typeIs, typeIsLike返回或检查值的底层 Go 类型。typeIsLike 还会解引用指针。typeIs "*io.Buffer" $val
反射deepEqual返回两个值是否“深度相等”。deepEqual (list 1 2) (list 1 2)
语义版本semver将字符串解析为 Semantic Version 2.0 对象。$v := semver "1.2.3-alpha.1+123"
语义版本semverCompare强大的版本比较功能,支持版本范围(如 ^1.2.0)。semverCompare ">= 1.2" "1.4.3"

通过这些函数,Sprig 极大地扩展了 Go 模板的能力,使其能够进行复杂的逻辑控制、数据结构操作以及安全相关的任务。

正如一个强大的工具箱,Sprig 提供了各种尺寸和用途的工具:从简单的字符串修剪到复杂的证书生成和语义版本比较,它确保了开发者可以在不离开模板环境的情况下高效地进行数据处理和布局控制。然而,如同任何强大的工具一样,使用 OS 函数或在模板中直接存储敏感数据时,也需要注意相关的安全风险。


也可以看看