Golang模板中如何分享自定义函数(FuncMap)
Golang模板中如何分享自定义函数(FuncMap)
引言
我是 Go 语言的新手。
我非常喜欢 Go 语言的模板功能。特别是 Template.Funcs 使得模板功能非常强大。
遗憾的是,官方提供的函数 似乎太少了。
也许是由于性能考虑,或者不想包含太多捆绑功能?我希望模板能尽可能多地使用 Go 语言的语法。
在 Hugo 中,它实现了许多函数,我发现这些函数非常有用。但可惜的是,我不够聪明,并且认为这个项目目前不太适合新手学习(当然,你也可以从旧的提交记录开始,但这非常困难)。(别担心,只要你的项目相关,无论难度如何,都欢迎分享🙂)
一旦你成为一名 Gopher,我坚信你或多或少都会创造出一些属于你自己的优秀函数。
我到底想做什么?
我创建这个帖子,是希望人们能够分享函数,以便我们都能从中受益。
我理解优秀的函数应该考虑到许多极端情况。但我认为那并不是最重要的事情,你不需要因为追求不完美而担心受到批评,任何分享都是值得的。你可以:
- ✍️ 直接在这里写一些代码
- 🔗 分享链接(博客、问题、文章、GitHub 项目等)
- 💪 建议或改进他人的代码
- 🧙 解释代码
- 🙏 询问你想要的函数以及如何实现它。
提前感谢所有回应的人,我对你们的奉献表示最崇高的敬意🙂
更多关于Golang模板中如何分享自定义函数(FuncMap)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
Hugo dict
如果你对 Hugo 中 dict 的实现感兴趣,这些链接可能对你有用:
不完善的 dict
我创建了一个简单的 dict 供参考。
func Dict(values ...interface{}) (map[string]interface{}, error) {
if len(values)%2 != 0 {
return nil, errors.New("parameters must be even")
}
dict := make(map[string]interface{})
var key, val interface{}
for {
key, val, values = values[0], values[1], values[2:]
switch reflect.ValueOf(key).Kind() {
case reflect.String:
dict[key.(string)] = val
default:
return nil, errors.New(`type must equal to "string"`)
}
if len(values) == 0 {
break
}
}
return dict, nil
}
用法
文本
{{- range $key, $val := (dict "User" "Carson" "Msg" "Test") -}}
{{$key}}: {{$val}}
{{ end -}}
{{ $myDict := dict "Msg" "Hello World" }}
{{$myDict.Msg}}
更多关于Golang模板中如何分享自定义函数(FuncMap)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go模板中分享自定义函数非常实用。以下是一个完整的示例,展示如何定义、注册和使用自定义函数:
package main
import (
"os"
"strings"
"text/template"
"time"
)
// 自定义函数集合
var templateFuncs = template.FuncMap{
// 字符串处理
"toUpper": strings.ToUpper,
"toLower": strings.ToLower,
"trimSpace": strings.TrimSpace,
// 日期时间格式化
"formatDate": func(t time.Time, layout string) string {
return t.Format(layout)
},
// 数学运算
"add": func(a, b int) int {
return a + b
},
"multiply": func(a, b int) int {
return a * b
},
// 逻辑判断
"inSlice": func(item string, list []string) bool {
for _, v := range list {
if v == item {
return true
}
}
return false
},
// 字符串截取
"truncate": func(s string, length int) string {
if len(s) <= length {
return s
}
return s[:length] + "..."
},
// HTML安全输出
"safeHTML": func(s string) template.HTML {
return template.HTML(s)
},
}
func main() {
// 创建模板并注册函数
tmpl := template.Must(template.New("demo").Funcs(templateFuncs).Parse(`
{{/* 使用字符串函数 */}}
原始字符串: "{{.Text}}"
大写: {{.Text | toUpper}}
小写: {{.Text | toLower}}
修剪后: "{{.Text | trimSpace}}"
截断(10): {{.Text | truncate 10}}
{{/* 使用日期函数 */}}
当前时间: {{formatDate .Now "2006-01-02 15:04:05"}}
{{/* 使用数学函数 */}}
{{$a := 5}}{{$b := 3}}
{{$a}} + {{$b}} = {{add $a $b}}
{{$a}} × {{$b}} = {{multiply $a $b}}
{{/* 使用逻辑函数 */}}
{{$list := .Items}}
{{range $item := $list}}
- {{$item}} 在列表中吗? {{inSlice $item $list}}
{{end}}
{{/* 使用安全HTML输出 */}}
{{safeHTML "<strong>加粗文本</strong>"}}
`))
// 模板数据
data := struct {
Text string
Now time.Time
Items []string
}{
Text: " Hello, Go Templates! ",
Now: time.Now(),
Items: []string{"apple", "banana", "orange"},
}
// 执行模板
if err := tmpl.Execute(os.Stdout, data); err != nil {
panic(err)
}
}
输出示例:
原始字符串: " Hello, Go Templates! "
大写: HELLO, GO TEMPLATES!
小写: hello, go templates!
修剪后: "Hello, Go Templates!"
截断(10): Hello, ...
当前时间: 2023-10-05 14:30:25
5 + 3 = 8
5 × 3 = 15
- apple 在列表中吗? true
- banana 在列表中吗? true
- orange 在列表中吗? true
<strong>加粗文本</strong>
更多实用函数示例:
// 文件大小格式化
func formatFileSize(bytes int64) string {
const unit = 1024
if bytes < unit {
return fmt.Sprintf("%d B", bytes)
}
div, exp := int64(unit), 0
for n := bytes / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}
// 相对时间显示
func relativeTime(t time.Time) string {
now := time.Now()
diff := now.Sub(t)
switch {
case diff < time.Minute:
return "刚刚"
case diff < time.Hour:
return fmt.Sprintf("%d分钟前", int(diff.Minutes()))
case diff < 24*time.Hour:
return fmt.Sprintf("%d小时前", int(diff.Hours()))
default:
return fmt.Sprintf("%d天前", int(diff.Hours()/24))
}
}
// 注册到FuncMap
var extendedFuncs = template.FuncMap{
"fileSize": formatFileSize,
"relativeTime": relativeTime,
// 合并之前的函数
"toUpper": templateFuncs["toUpper"],
"toLower": templateFuncs["toLower"],
}
这些函数可以直接在模板中使用:
tmpl := `文件大小: {{.Size | fileSize}}
更新时间: {{.UpdateTime | relativeTime}}`
要分享函数库,可以创建独立的Go模块:
// 在单独包中定义
package templatefuncs
import (
"html/template"
"strings"
"time"
)
// GetFuncMap 返回所有自定义函数
func GetFuncMap() template.FuncMap {
return template.FuncMap{
"toUpper": strings.ToUpper,
"formatDate": formatDate,
"truncate": truncateString,
"safeHTML": safeHTML,
"fileSize": formatFileSize,
"relativeTime": relativeTime,
}
}
// 在其他项目中导入使用
import "github.com/yourname/templatefuncs"
func main() {
tmpl := template.New("").Funcs(templatefuncs.GetFuncMap())
}
这种方式允许通过Go模块系统分享和复用自定义模板函数。

