当前位置: 首页 > news >正文

Go Web 编程快速入门 07 - 模板(1):语法与最佳实践

在现代Web开发中,模板引擎是分离业务逻辑与视图展示的重要工具。Go语言内置的text/templatehtml/template包提供了强大而安全的模板功能。本章将深入探讨Go模板的语法基础和最佳实践,帮助你构建高效、安全的Web应用。

1. Go模板系统概述

1.1 模板包选择

Go提供了两个模板包:

package mainimport ("text/template"  // 通用文本模板"html/template"  // HTML模板,具有自动转义功能"fmt""os""strings"
)// TemplateManager 模板管理器
type TemplateManager struct {textTemplates map[string]*text.Template    // 文本模板集合htmlTemplates map[string]*html.template.Template  // HTML模板集合
}// NewTemplateManager 创建模板管理器
func NewTemplateManager() *TemplateManager {return &TemplateManager{textTemplates: make(map[string]*text.Template),htmlTemplates: make(map[string]*html.template.Template),}
}// AddTextTemplate 添加文本模板
func (tm *TemplateManager) AddTextTemplate(name, content string) error {tmpl, err := text.template.New(name).Parse(content)if err != nil {return fmt.Errorf("解析文本模板失败: %w", err)}tm.textTemplates[name] = tmplreturn nil
}// AddHTMLTemplate 添加HTML模板
func (tm *TemplateManager) AddHTMLTemplate(name, content string) error {tmpl, err := html.template.New(name).Parse(content)if err != nil {return fmt.Errorf("解析HTML模板失败: %w", err)}tm.htmlTemplates[name] = tmplreturn nil
}// ExecuteText 执行文本模板
func (tm *TemplateManager) ExecuteText(name string, data interface{}) (string, error) {tmpl, exists := tm.textTemplates[name]if !exists {return "", fmt.Errorf("文本模板 %s 不存在", name)}var buf strings.Builderif err := tmpl.Execute(&buf, data); err != nil {return "", fmt.Errorf("执行文本模板失败: %w", err)}return buf.String(), nil
}// ExecuteHTML 执行HTML模板
func (tm *TemplateManager) ExecuteHTML(name string, data interface{}) (string, error) {tmpl, exists := tm.htmlTemplates[name]if !exists {return "", fmt.Errorf("HTML模板 %s 不存在", name)}var buf strings.Builderif err := tmpl.Execute(&buf, data); err != nil {return "", fmt.Errorf("执行HTML模板失败: %w", err)}return buf.String(), nil
}

1.2 模板安全性对比

// SecurityDemo 安全性演示
type SecurityDemo struct {manager *TemplateManager
}// NewSecurityDemo 创建安全性演示
func NewSecurityDemo() *SecurityDemo {return &SecurityDemo{manager: NewTemplateManager(),}
}// DemonstrateEscaping 演示转义功能
func (sd *SecurityDemo) DemonstrateEscaping() {// 用户输入包含潜在的XSS攻击userInput := "<script>alert('XSS攻击!');</script>"data := map[string]interface{}{"UserInput": userInput,"SafeHTML":  "<b>安全的HTML</b>",}// 文本模板 - 不进行转义textTemplate := `用户输入: {{.UserInput}}`sd.manager.AddTextTemplate("unsafe", textTemplate)// HTML模板 - 自动转义htmlTemplate := `<div>用户输入: {{.UserInput}}</div>
<div>安全HTML: {{.SafeHTML}}</div>`sd.manager.AddHTMLTemplate("safe", htmlTemplate)// 执行并比较结果textResult, _ := sd.manager.ExecuteText("unsafe", data)htmlResult, _ := sd.manager.ExecuteHTML("safe", data)fmt.Println("=== 安全性对比 ===")fmt.Println("文本模板结果(不安全):")fmt.Println(textResult)fmt.Println("\nHTML模板结果(安全):")fmt.Println(htmlResult)
}

2. 模板语法基础

2.1 变量与数据访问

// DataAccessDemo 数据访问演示
type DataAccessDemo struct {manager *TemplateManager
}// User 用户结构体
type User struct {ID       int               `json:"id"`Name     string            `json:"name"`Email    string            `json:"email"`Profile  *UserProfile      `json:"profile"`Tags     []string          `json:"tags"`Settings map[string]string `json:"settings"`
}// UserProfile 用户档案
type UserProfile struct {Avatar   string `json:"avatar"`Bio      string `json:"bio"`Location string `json:"location"`
}// NewDataAccessDemo 创建数据访问演示
func NewDataAccessDemo() *DataAccessDemo {return &DataAccessDemo{manager: NewTemplateManager(),}
}// SetupTemplates 设置模板
func (dad *DataAccessDemo) SetupTemplates() {// 基础变量访问模板basicTemplate := `
用户信息:
- ID: {{.ID}}
- 姓名: {{.Name}}
- 邮箱: {{.Email}}
`// 嵌套结构访问模板nestedTemplate := `
用户档案:
- 头像: {{.Profile.Avatar}}
- 简介: {{.Profile.Bio}}
- 位置: {{.Profile.Location}}
`// 数组访问模板arrayTemplate := `
用户标签:
{{range $index, $tag := .Tags}}
- [{{$index}}] {{$tag}}
{{end}}
`// Map访问模板mapTemplate := `
用户设置:
{{range $key, $value := .Settings}}
- {{$key}}: {{$value}}
{{end}}
`// 复合模板complexTemplate := `
=== 完整用户信息 ===
基本信息:ID: {{.ID}}姓名: {{.Name}}邮箱: {{.Email}}档案信息:
{{if .Profile}}头像: {{.Profile.Avatar}}简介: {{.Profile.Bio}}位置: {{.Profile.Location}}
{{else}}档案信息不完整
{{end}}标签 ({{len .Tags}} 个):
{{range $i, $tag := .Tags}}{{add $i 1}}. {{$tag}}
{{end}}设置:
{{range $key, $value := .Settings}}{{$key}} = {{$value}}
{{end}}
`dad.manager.AddTextTemplate("basic", basicTemplate)dad.manager.AddTextTemplate("nested", nestedTemplate)dad.manager.AddTextTemplate("array", arrayTemplate)dad.manager.AddTextTemplate("map", mapTemplate)dad.manager.AddTextTemplate("complex", complexTemplate)
}// DemonstrateDataAccess 演示数据访问
func (dad *DataAccessDemo) DemonstrateDataAccess() {// 创建测试数据user := &User{ID:    1001,Name:  "张三",Email: "zhangsan@example.com",Profile: &UserProfile{Avatar:   "/avatars/zhangsan.jpg",Bio:      "Go语言爱好者,Web开发工程师",Location: "北京",},Tags: []string{"Go", "Web开发", "微服务", "云原生"},Settings: map[string]string{"theme":    "dark","language": "zh-CN","timezone": "Asia/Shanghai",},}dad.SetupTemplates()// 演示各种数据访问templates := []string{"basic", "nested", "array", "map", "complex"}for _, tmplName := range templates {fmt.Printf("\n=== %s 模板结果 ===\n", tmplName)result, err := dad.manager.ExecuteText(tmplName, user)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Println(result)}
}

2.2 条件控制语句

// ConditionalDemo 条件控制演示
type ConditionalDemo struct {manager *TemplateManager
}// Product 产品结构体
type Product struct {ID          int     `json:"id"`Name        string  `json:"name"`Price       float64 `json:"price"`Stock       int     `json:"stock"`Category    string  `json:"category"`IsActive    bool    `json:"is_active"`Description string  `json:"description"`Tags        []string `json:"tags"`
}// NewConditionalDemo 创建条件控制演示
func NewConditionalDemo() *ConditionalDemo {return &ConditionalDemo{manager: NewTemplateManager(),}
}// SetupConditionalTemplates 设置条件模板
func (cd *ConditionalDemo) SetupConditionalTemplates() {// 基础if条件模板basicIfTemplate := `
产品: {{.Name}}
{{if .IsActive}}
✅ 产品已激活
{{else}}
❌ 产品未激活
{{end}}
`// 复杂条件判断模板complexIfTemplate := `
产品状态检查: {{.Name}}
{{if .IsActive}}{{if gt .Stock 0}}{{if lt .Stock 10}}
✅ 库存紧张 (剩余: {{.Stock}}){{else}}
✅ 库存充足 (剩余: {{.Stock}}){{end}}{{else}}
❌ 库存不足{{end}}
{{else}}
❌ 产品未激活
{{end}}
`// 价格区间判断模板priceRangeTemplate := `
产品: {{.Name}}
价格: ¥{{printf "%.2f" .Price}}
{{if lt .Price 100}}
💰 经济实惠
{{else if lt .Price 500}}
💎 中等价位
{{else if lt .Price 1000}}
👑 高端产品
{{else}}
💸 奢侈品
{{end}}
`// 多条件组合模板multiConditionTemplate := `
=== 产品评估报告 ===
产品: {{.Name}} (ID: {{.ID}})状态评估:
{{if and .IsActive (gt .Stock 0)}}
✅ 可销售状态
{{else if .IsActive}}
⚠️  已激活但库存不足
{{else}}
❌ 产品未激活
{{end}}价格策略:
{{if or (eq .Category "electronics") (eq .Category "books")}}{{if lt .Price 200}}
🎯 推荐促销{{else}}
💼 正常销售{{end}}
{{else}}
🏷️  其他类别产品
{{end}}库存警告:
{{if le .Stock 5}}
🚨 库存严重不足!
{{else if le .Stock 20}}
⚠️  库存偏低
{{else}}
✅ 库存正常
{{end}}
`// 字符串条件模板stringConditionTemplate := `
产品分类分析: {{.Name}}
{{if eq .Category "electronics"}}
📱 电子产品 - 需要技术支持
{{else if eq .Category "books"}}
📚 图书产品 - 需要内容审核
{{else if eq .Category "clothing"}}
👕 服装产品 - 需要尺码管理
{{else}}
📦 其他类别产品
{{end}}描述检查:
{{if .Description}}{{if gt (len .Description) 100}}
📝 详细描述 ({{len .Description}} 字符){{else}}
📄 简短描述 ({{len .Description}} 字符){{end}}
{{else}}
❌ 缺少产品描述
{{end}}
`cd.manager.AddTextTemplate("basic_if", basicIfTemplate)cd.manager.AddTextTemplate("complex_if", complexIfTemplate)cd.manager.AddTextTemplate("price_range", priceRangeTemplate)cd.manager.AddTextTemplate("multi_condition", multiConditionTemplate)cd.manager.AddTextTemplate("string_condition", stringConditionTemplate)
}// DemonstrateConditionals 演示条件控制
func (cd *ConditionalDemo) DemonstrateConditionals() {// 创建不同状态的产品进行测试products := []*Product{{ID:          1,Name:        "iPhone 15 Pro",Price:       7999.00,Stock:       3,Category:    "electronics",IsActive:    true,Description: "最新款iPhone,配备A17 Pro芯片,钛金属设计,支持USB-C接口。",Tags:        []string{"手机", "苹果", "高端"},},{ID:          2,Name:        "Go语言编程",Price:       89.00,Stock:       0,Category:    "books",IsActive:    true,Description: "深入学习Go语言的经典教程",Tags:        []string{"编程", "Go", "教程"},},{ID:          3,Name:        "休闲T恤",Price:       59.00,Stock:       150,Category:    "clothing",IsActive:    false,Description: "",Tags:        []string{"服装", "休闲"},},}cd.SetupConditionalTemplates()templates := []string{"basic_if", "complex_if", "price_range", "multi_condition", "string_condition"}for _, product := range products {fmt.Printf("\n" + strings.Repeat("=", 50))fmt.Printf("\n测试产品: %s\n", product.Name)fmt.Println(strings.Repeat("=", 50))for _, tmplName := range templates {fmt.Printf("\n--- %s ---\n", tmplName)result, err := cd.manager.ExecuteText(tmplName, product)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Print(result)}}
}

2.3 循环控制语句

// LoopDemo 循环控制演示
type LoopDemo struct {manager *TemplateManager
}// BlogPost 博客文章
type BlogPost struct {ID       int      `json:"id"`Title    string   `json:"title"`Content  string   `json:"content"`Author   string   `json:"author"`Tags     []string `json:"tags"`Comments []Comment `json:"comments"`Meta     map[string]interface{} `json:"meta"`
}// Comment 评论
type Comment struct {ID      int    `json:"id"`Author  string `json:"author"`Content string `json:"content"`Likes   int    `json:"likes"`
}// BlogData 博客数据
type BlogData struct {Posts      []BlogPost            `json:"posts"`Categories map[string][]BlogPost `json:"categories"`Stats      map[string]int        `json:"stats"`
}// NewLoopDemo 创建循环演示
func NewLoopDemo() *LoopDemo {return &LoopDemo{manager: NewTemplateManager(),}
}// SetupLoopTemplates 设置循环模板
func (ld *LoopDemo) SetupLoopTemplates() {// 基础range循环模板basicRangeTemplate := `
=== 文章列表 ===
{{range .Posts}}
📄 {{.Title}} (作者: {{.Author}})
{{end}}
`// 带索引的循环模板indexRangeTemplate := `
=== 编号文章列表 ===
{{range $index, $post := .Posts}}
{{add $index 1}}. {{$post.Title}}作者: {{$post.Author}}标签: {{join $post.Tags ", "}}
{{end}}
`// 嵌套循环模板nestedRangeTemplate := `
=== 文章详情 ===
{{range $postIndex, $post := .Posts}}📄 文章 {{add $postIndex 1}}: {{$post.Title}}作者: {{$post.Author}}🏷️  标签:{{range $tagIndex, $tag := $post.Tags}}- [{{$tagIndex}}] {{$tag}}{{end}}💬 评论 ({{len $post.Comments}} 条):{{range $commentIndex, $comment := $post.Comments}}{{add $commentIndex 1}}. {{$comment.Author}}: {{$comment.Content}}👍 {{$comment.Likes}} 个赞{{end}}
{{end}}
`// Map循环模板mapRangeTemplate := `
=== 分类统计 ===
{{range $category, $posts := .Categories}}
📂 {{$category}} ({{len $posts}} 篇文章):
{{range $posts}}- {{.Title}}
{{end}}
{{end}}=== 网站统计 ===
{{range $key, $value := .Stats}}
📊 {{$key}}: {{$value}}
{{end}}
`// 条件循环模板conditionalRangeTemplate := `
=== 热门文章筛选 ===
{{range .Posts}}
{{if gt (len .Comments) 2}}
🔥 热门: {{.Title}}评论数: {{len .Comments}}{{range .Comments}}💬 {{.Author}}: {{.Content}}{{end}}
{{end}}
{{end}}=== 长标题文章 ===
{{range .Posts}}
{{if gt (len .Title) 10}}
📝 {{.Title}} ({{len .Title}} 字符)
{{end}}
{{end}}
`// 复杂循环控制模板complexRangeTemplate := `
=== 综合文章报告 ===
{{$totalPosts := len .Posts}}
{{$totalComments := 0}}
{{range .Posts}}
{{$totalComments = add $totalComments (len .Comments)}}
{{end}}📊 总体统计:
- 文章总数: {{$totalPosts}}
- 评论总数: {{$totalComments}}
- 平均评论数: {{if gt $totalPosts 0}}{{div $totalComments $totalPosts}}{{else}}0{{end}}📄 文章详细分析:
{{range $index, $post := .Posts}}
{{$commentCount := len $post.Comments}}
{{$isPopular := gt $commentCount 2}}[{{add $index 1}}] {{$post.Title}}作者: {{$post.Author}}评论: {{$commentCount}} 条状态: {{if $isPopular}}🔥 热门{{else}}📝 普通{{end}}标签: {{if $post.Tags}}{{join $post.Tags " | "}}{{else}}无标签{{end}}{{if $isPopular}}热门评论:{{range $post.Comments}}💬 {{.Author}}: {{.Content}} (👍{{.Likes}}){{end}}{{end}}
{{end}}
`ld.manager.AddTextTemplate("basic_range", basicRangeTemplate)ld.manager.AddTextTemplate("index_range", indexRangeTemplate)ld.manager.AddTextTemplate("nested_range", nestedRangeTemplate)ld.manager.AddTextTemplate("map_range", mapRangeTemplate)ld.manager.AddTextTemplate("conditional_range", conditionalRangeTemplate)ld.manager.AddTextTemplate("complex_range", complexRangeTemplate)
}// DemonstrateLoops 演示循环控制
func (ld *LoopDemo) DemonstrateLoops() {// 创建测试数据posts := []BlogPost{{ID:      1,Title:   "Go语言Web开发入门",Content: "本文介绍Go语言Web开发的基础知识...",Author:  "张三",Tags:    []string{"Go", "Web", "入门"},Comments: []Comment{{ID: 1, Author: "李四", Content: "写得很好!", Likes: 5},{ID: 2, Author: "王五", Content: "学到了很多", Likes: 3},{ID: 3, Author: "赵六", Content: "期待更多内容", Likes: 2},},Meta: map[string]interface{}{"views":     1250,"published": true,},},{ID:      2,Title:   "模板引擎最佳实践",Content: "深入探讨Go模板引擎的使用技巧...",Author:  "李四",Tags:    []string{"Go", "模板", "最佳实践"},Comments: []Comment{{ID: 4, Author: "张三", Content: "实用性很强", Likes: 8},},Meta: map[string]interface{}{"views":     890,"published": true,},},{ID:      3,Title:   "微服务架构设计",Content: "介绍微服务架构的设计原则和实践...",Author:  "王五",Tags:    []string{"微服务", "架构", "设计"},Comments: []Comment{{ID: 5, Author: "张三", Content: "架构思路清晰", Likes: 6},{ID: 6, Author: "李四", Content: "很有启发", Likes: 4},{ID: 7, Author: "赵六", Content: "实践性强", Likes: 7},{ID: 8, Author: "钱七", Content: "收藏了", Likes: 2},},Meta: map[string]interface{}{"views":     2100,"published": true,},},}// 按分类组织文章categories := map[string][]BlogPost{"编程语言": {posts[0], posts[1]},"架构设计": {posts[2]},"Web开发":  {posts[0]},}// 统计信息stats := map[string]int{"总文章数": len(posts),"总作者数": 3,"总评论数": 8,"总浏览数": 4240,}blogData := &BlogData{Posts:      posts,Categories: categories,Stats:      stats,}ld.SetupLoopTemplates()templates := []string{"basic_range", "index_range", "nested_range", "map_range", "conditional_range", "complex_range"}for _, tmplName := range templates {fmt.Printf("\n" + strings.Repeat("=", 60))fmt.Printf("\n%s 模板结果", tmplName)fmt.Printf("\n" + strings.Repeat("=", 60) + "\n")result, err := ld.manager.ExecuteText(tmplName, blogData)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Print(result)}
}

3. 模板函数与管道

3.1 内置函数使用

// BuiltinFunctionDemo 内置函数演示
type BuiltinFunctionDemo struct {manager *TemplateManager
}// NewBuiltinFunctionDemo 创建内置函数演示
func NewBuiltinFunctionDemo() *BuiltinFunctionDemo {return &BuiltinFunctionDemo{manager: NewTemplateManager(),}
}// SetupBuiltinFunctionTemplates 设置内置函数模板
func (bfd *BuiltinFunctionDemo) SetupBuiltinFunctionTemplates() {// 数学运算函数模板mathTemplate := `
=== 数学运算函数 ===
原始数值: {{.Number}}
加法: {{add .Number 10}} ({{.Number}} + 10)
减法: {{sub .Number 5}} ({{.Number}} - 5)
乘法: {{mul .Number 2}} ({{.Number}} * 2)
除法: {{div .Number 3}} ({{.Number}} / 3)
取模: {{mod .Number 7}} ({{.Number}} % 7)比较运算:
等于10: {{eq .Number 10}}
不等于10: {{ne .Number 10}}
大于5: {{gt .Number 5}}
大于等于10: {{ge .Number 10}}
小于20: {{lt .Number 20}}
小于等于15: {{le .Number 15}}
`// 逻辑运算函数模板logicTemplate := `
=== 逻辑运算函数 ===
布尔值1: {{.Bool1}}
布尔值2: {{.Bool2}}
AND运算: {{and .Bool1 .Bool2}}
OR运算: {{or .Bool1 .Bool2}}
NOT运算1: {{not .Bool1}}
NOT运算2: {{not .Bool2}}复合逻辑:
{{if and .Bool1 (not .Bool2)}}
✅ Bool1为真且Bool2为假
{{else}}
❌ 条件不满足
{{end}}
`// 字符串处理函数模板stringTemplate := `
=== 字符串处理函数 ===
原始字符串: "{{.Text}}"
长度: {{len .Text}}
打印格式化: {{printf "格式化: [%s]" .Text}}
HTML转义: {{html .Text}}
URL查询转义: {{urlquery .Text}}
JavaScript转义: {{js .Text}}数组处理:
标签数组: {{.Tags}}
数组长度: {{len .Tags}}
索引访问: {{index .Tags 0}} (第一个元素)
{{if gt (len .Tags) 2}}
第三个元素: {{index .Tags 2}}
{{end}}
`bfd.manager.AddTextTemplate("math", mathTemplate)bfd.manager.AddTextTemplate("logic", logicTemplate)bfd.manager.AddTextTemplate("string", stringTemplate)
}// DemonstrateBuiltinFunctions 演示内置函数
func (bfd *BuiltinFunctionDemo) DemonstrateBuiltinFunctions() {testData := map[string]interface{}{"Number": 15,"Bool1":  true,"Bool2":  false,"Text":   "<script>alert('Hello & 世界');</script>","Tags":   []string{"Go", "Web", "模板", "函数"},}bfd.SetupBuiltinFunctionTemplates()templates := []string{"math", "logic", "string"}for _, tmplName := range templates {fmt.Printf("\n" + strings.Repeat("-", 50))fmt.Printf("\n%s 模板结果", tmplName)fmt.Printf("\n" + strings.Repeat("-", 50) + "\n")result, err := bfd.manager.ExecuteText(tmplName, testData)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Print(result)}
}

3.2 自定义函数

// CustomFunctionDemo 自定义函数演示
type CustomFunctionDemo struct {textTemplates map[string]*text.TemplatehtmlTemplates map[string]*html.template.Template
}// NewCustomFunctionDemo 创建自定义函数演示
func NewCustomFunctionDemo() *CustomFunctionDemo {return &CustomFunctionDemo{textTemplates: make(map[string]*text.Template),htmlTemplates: make(map[string]*html.template.Template),}
}// GetCustomFuncMap 获取自定义函数映射
func (cfd *CustomFunctionDemo) GetCustomFuncMap() text.template.FuncMap {return text.template.FuncMap{// 字符串处理函数"upper":     strings.ToUpper,           // 转大写"lower":     strings.ToLower,           // 转小写"title":     strings.Title,             // 标题格式"trim":      strings.TrimSpace,         // 去除首尾空格"replace":   strings.ReplaceAll,        // 字符串替换"contains":  strings.Contains,          // 包含检查"hasPrefix": strings.HasPrefix,         // 前缀检查"hasSuffix": strings.HasSuffix,         // 后缀检查"split":     strings.Split,             // 字符串分割"join":      strings.Join,              // 字符串连接// 数学计算函数"abs": func(n int) int {                // 绝对值if n < 0 {return -n}return n},"max": func(a, b int) int {             // 最大值if a > b {return a}return b},"min": func(a, b int) int {             // 最小值if a < b {return a}return b},"pow": func(base, exp int) int {        // 幂运算result := 1for i := 0; i < exp; i++ {result *= base}return result},// 时间处理函数"now": func() string {                  // 当前时间return fmt.Sprintf("%v", "2024-01-15 10:30:00")},"formatTime": func(layout, timeStr string) string { // 时间格式化return fmt.Sprintf("格式化时间: %s", timeStr)},// 数组/切片处理函数"first": func(slice []interface{}) interface{} { // 第一个元素if len(slice) > 0 {return slice[0]}return nil},"last": func(slice []interface{}) interface{} {  // 最后一个元素if len(slice) > 0 {return slice[len(slice)-1]}return nil},"reverse": func(slice []string) []string {       // 反转数组result := make([]string, len(slice))for i, v := range slice {result[len(slice)-1-i] = v}return result},"unique": func(slice []string) []string {        // 去重seen := make(map[string]bool)var result []stringfor _, v := range slice {if !seen[v] {seen[v] = trueresult = append(result, v)}}return result},// 条件判断函数"isEmpty": func(s string) bool {        // 是否为空return strings.TrimSpace(s) == ""},"isNotEmpty": func(s string) bool {     // 是否非空return strings.TrimSpace(s) != ""},"default": func(defaultVal, val interface{}) interface{} { // 默认值if val == nil || val == "" {return defaultVal}return val},// 格式化函数"currency": func(amount float64) string { // 货币格式化return fmt.Sprintf("¥%.2f", amount)},"percentage": func(val float64) string {  // 百分比格式化return fmt.Sprintf("%.1f%%", val*100)},"fileSize": func(bytes int64) string {    // 文件大小格式化const unit = 1024if bytes < unit {return fmt.Sprintf("%d B", bytes)}div, exp := int64(unit), 0for n := bytes / unit; n >= unit; n /= unit {div *= unitexp++}return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])},// 安全函数"safeHTML": func(s string) html.template.HTML { // 安全HTMLreturn html.template.HTML(s)},"safeCSS": func(s string) html.template.CSS {   // 安全CSSreturn html.template.CSS(s)},"safeJS": func(s string) html.template.JS {     // 安全JavaScriptreturn html.template.JS(s)},}
}// AddTextTemplateWithFuncs 添加带自定义函数的文本模板
func (cfd *CustomFunctionDemo) AddTextTemplateWithFuncs(name, content string) error {tmpl := text.template.New(name).Funcs(cfd.GetCustomFuncMap())var err errortmpl, err = tmpl.Parse(content)if err != nil {return fmt.Errorf("解析模板失败: %w", err)}cfd.textTemplates[name] = tmplreturn nil
}// ExecuteTextTemplate 执行文本模板
func (cfd *CustomFunctionDemo) ExecuteTextTemplate(name string, data interface{}) (string, error) {tmpl, exists := cfd.textTemplates[name]if !exists {return "", fmt.Errorf("模板 %s 不存在", name)}var buf strings.Builderif err := tmpl.Execute(&buf, data); err != nil {return "", fmt.Errorf("执行模板失败: %w", err)}return buf.String(), nil
}// SetupCustomFunctionTemplates 设置自定义函数模板
func (cfd *CustomFunctionDemo) SetupCustomFunctionTemplates() {// 字符串处理模板stringFuncTemplate := `
=== 字符串处理函数 ===
原始文本: "{{.Text}}"
大写: {{upper .Text}}
小写: {{lower .Text}}
标题格式: {{title .Text}}
去空格: "{{trim .SpacedText}}"
替换: {{replace .Text "Go" "Golang"}}
包含"Web": {{contains .Text "Web"}}
以"Go"开头: {{hasPrefix .Text "Go"}}
以"开发"结尾: {{hasSuffix .Text "开发"}}分割与连接:
分割结果: {{split .Text " "}}
连接标签: {{join .Tags " | "}}
`// 数学计算模板mathFuncTemplate := `
=== 数学计算函数 ===
数值A: {{.NumA}}, 数值B: {{.NumB}}
绝对值A: {{abs .NumA}}
最大值: {{max .NumA .NumB}}
最小值: {{min .NumA .NumB}}
A的3次方: {{pow .NumA 3}}
B的2次方: {{pow .NumB 2}}
`// 数组处理模板arrayFuncTemplate := `
=== 数组处理函数 ===
原始数组: {{.Items}}
第一个元素: {{first .Items}}
最后一个元素: {{last .Items}}
反转数组: {{reverse .StringItems}}
去重数组: {{unique .DuplicateItems}}
数组长度: {{len .Items}}
`// 格式化函数模板formatFuncTemplate := `
=== 格式化函数 ===
价格: {{currency .Price}}
折扣率: {{percentage .Discount}}
文件大小: {{fileSize .FileSize}}
当前时间: {{now}}
格式化时间: {{formatTime "2006-01-02" "2024-01-15"}}条件判断:
空字符串检查: {{isEmpty .EmptyText}}
非空字符串检查: {{isNotEmpty .Text}}
默认值处理: {{default "默认标题" .EmptyTitle}}
`// 复合函数模板complexFuncTemplate := `
=== 复合函数应用 ===
{{$title := default "无标题" .Title}}
{{$cleanTitle := trim $title}}
{{$upperTitle := upper $cleanTitle}}处理后标题: {{$upperTitle}}价格信息:
{{range .Products}}
- {{.Name}}: {{currency .Price}}{{if gt .Discount 0}}折扣: {{percentage .Discount}}{{end}}文件大小: {{fileSize .Size}}
{{end}}标签处理:
{{$uniqueTags := unique .AllTags}}
{{$reversedTags := reverse $uniqueTags}}
去重后标签: {{join $uniqueTags " | "}}
反转后标签: {{join $reversedTags " | "}}数学计算:
{{range .Numbers}}
数值: {{.}}, 绝对值: {{abs .}}, 平方: {{pow . 2}}
{{end}}
`cfd.AddTextTemplateWithFuncs("string_func", stringFuncTemplate)cfd.AddTextTemplateWithFuncs("math_func", mathFuncTemplate)cfd.AddTextTemplateWithFuncs("array_func", arrayFuncTemplate)cfd.AddTextTemplateWithFuncs("format_func", formatFuncTemplate)cfd.AddTextTemplateWithFuncs("complex_func", complexFuncTemplate)
}// DemonstrateCustomFunctions 演示自定义函数
func (cfd *CustomFunctionDemo) DemonstrateCustomFunctions() {// 创建测试数据testData := map[string]interface{}{"Text":       "Go Web 开发","SpacedText": "  带空格的文本  ","EmptyText":  "","EmptyTitle": "","Title":      "  Go语言教程  ","NumA":       -15,"NumB":       8,"Tags":       []string{"Go", "Web", "开发", "教程"},"Items":      []interface{}{"第一个", "第二个", "第三个"},"StringItems": []string{"Apple", "Banana", "Cherry"},"DuplicateItems": []string{"Go", "Web", "Go", "开发", "Web", "教程"},"Price":      299.99,"Discount":   0.15,"FileSize":   int64(1048576), // 1MB"Products": []map[string]interface{}{{"Name": "Go语言书籍", "Price": 89.00, "Discount": 0.1, "Size": int64(2048)},{"Name": "Web开发工具", "Price": 199.00, "Discount": 0.0, "Size": int64(5242880)},},"AllTags": []string{"Go", "Web", "开发", "Go", "教程", "Web", "实践"},"Numbers": []int{-5, 3, -8, 12, 0},}cfd.SetupCustomFunctionTemplates()templates := []string{"string_func", "math_func", "array_func", "format_func", "complex_func"}for _, tmplName := range templates {fmt.Printf("\n" + strings.Repeat("=", 60))fmt.Printf("\n%s 模板结果", tmplName)fmt.Printf("\n" + strings.Repeat("=", 60) + "\n")result, err := cfd.ExecuteTextTemplate(tmplName, testData)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Print(result)}
}

4. 综合实践项目:博客系统模板

// BlogTemplateSystem 博客模板系统
type BlogTemplateSystem struct {textTemplates map[string]*text.TemplatehtmlTemplates map[string]*html.template.TemplatefuncMap       text.template.FuncMap
}// Article 文章结构
type Article struct {ID          int       `json:"id"`Title       string    `json:"title"`Content     string    `json:"content"`Summary     string    `json:"summary"`Author      Author    `json:"author"`Category    Category  `json:"category"`Tags        []Tag     `json:"tags"`Comments    []Comment `json:"comments"`PublishedAt string    `json:"published_at"`UpdatedAt   string    `json:"updated_at"`ViewCount   int       `json:"view_count"`LikeCount   int       `json:"like_count"`Status      string    `json:"status"` // published, draft, archived
}// Author 作者结构
type Author struct {ID     int    `json:"id"`Name   string `json:"name"`Email  string `json:"email"`Avatar string `json:"avatar"`Bio    string `json:"bio"`
}// Category 分类结构
type Category struct {ID          int    `json:"id"`Name        string `json:"name"`Description string `json:"description"`Color       string `json:"color"`
}// Tag 标签结构
type Tag struct {ID    int    `json:"id"`Name  string `json:"name"`Color string `json:"color"`
}// BlogSite 博客站点信息
type BlogSite struct {Title       string             `json:"title"`Description string             `json:"description"`Articles    []Article          `json:"articles"`Categories  []Category         `json:"categories"`Tags        []Tag              `json:"tags"`Authors     []Author           `json:"authors"`Stats       map[string]int     `json:"stats"`Config      map[string]string  `json:"config"`
}// NewBlogTemplateSystem 创建博客模板系统
func NewBlogTemplateSystem() *BlogTemplateSystem {bts := &BlogTemplateSystem{textTemplates: make(map[string]*text.Template),htmlTemplates: make(map[string]*html.template.Template),}// 设置自定义函数bts.funcMap = text.template.FuncMap{// 字符串处理"truncate": func(s string, length int) string {if len(s) <= length {return s}return s[:length] + "..."},"slug": func(s string) string {return strings.ToLower(strings.ReplaceAll(s, " ", "-"))},// 时间处理"timeAgo": func(timeStr string) string {return timeStr + " (3天前)" // 简化实现},"formatDate": func(timeStr string) string {return "2024年1月15日" // 简化实现},// 数组处理"slice": func(items []Article, start, end int) []Article {if start < 0 || start >= len(items) {return []Article{}}if end > len(items) {end = len(items)}return items[start:end]},// 统计函数"countByStatus": func(articles []Article, status string) int {count := 0for _, article := range articles {if article.Status == status {count++}}return count},"countByCategory": func(articles []Article, categoryID int) int {count := 0for _, article := range articles {if article.Category.ID == categoryID {count++}}return count},// 过滤函数"filterByStatus": func(articles []Article, status string) []Article {var filtered []Articlefor _, article := range articles {if article.Status == status {filtered = append(filtered, article)}}return filtered},"filterByCategory": func(articles []Article, categoryID int) []Article {var filtered []Articlefor _, article := range articles {if article.Category.ID == categoryID {filtered = append(filtered, article)}}return filtered},// 排序函数"sortByViews": func(articles []Article) []Article {// 简化实现,实际应该进行排序return articles},"sortByDate": func(articles []Article) []Article {// 简化实现,实际应该进行排序return articles},// 格式化函数"formatNumber": func(n int) string {if n >= 1000000 {return fmt.Sprintf("%.1fM", float64(n)/1000000)} else if n >= 1000 {return fmt.Sprintf("%.1fK", float64(n)/1000)}return fmt.Sprintf("%d", n)},// 安全函数"safeHTML": func(s string) html.template.HTML {return html.template.HTML(s)},}return bts
}// AddTemplate 添加模板
func (bts *BlogTemplateSystem) AddTemplate(name, content string, isHTML bool) error {if isHTML {tmpl := html.template.New(name).Funcs(html.template.FuncMap(bts.funcMap))var err errortmpl, err = tmpl.Parse(content)if err != nil {return fmt.Errorf("解析HTML模板失败: %w", err)}bts.htmlTemplates[name] = tmpl} else {tmpl := text.template.New(name).Funcs(bts.funcMap)var err errortmpl, err = tmpl.Parse(content)if err != nil {return fmt.Errorf("解析文本模板失败: %w", err)}bts.textTemplates[name] = tmpl}return nil
}// ExecuteTemplate 执行模板
func (bts *BlogTemplateSystem) ExecuteTemplate(name string, data interface{}, isHTML bool) (string, error) {var buf strings.Builderif isHTML {tmpl, exists := bts.htmlTemplates[name]if !exists {return "", fmt.Errorf("HTML模板 %s 不存在", name)}if err := tmpl.Execute(&buf, data); err != nil {return "", fmt.Errorf("执行HTML模板失败: %w", err)}} else {tmpl, exists := bts.textTemplates[name]if !exists {return "", fmt.Errorf("文本模板 %s 不存在", name)}if err := tmpl.Execute(&buf, data); err != nil {return "", fmt.Errorf("执行文本模板失败: %w", err)}}return buf.String(), nil
}// SetupBlogTemplates 设置博客模板
func (bts *BlogTemplateSystem) SetupBlogTemplates() {// 文章列表模板articleListTemplate := `
=== {{.Title}} ===
{{.Description}}📊 站点统计:
{{range $key, $value := .Stats}}
- {{$key}}: {{formatNumber $value}}
{{end}}📂 分类列表:
{{range .Categories}}
- {{.Name}} ({{countByCategory $.Articles .ID}} 篇文章){{.Description}}
{{end}}📄 最新文章 ({{len .Articles}} 篇):
{{range $index, $article := .Articles}}
{{add $index 1}}. {{$article.Title}}作者: {{$article.Author.Name}}分类: {{$article.Category.Name}}发布: {{formatDate $article.PublishedAt}}浏览: {{formatNumber $article.ViewCount}} | 点赞: {{formatNumber $article.LikeCount}}摘要: {{truncate $article.Summary 100}}标签: {{range $article.Tags}}#{{.Name}} {{end}}状态: {{if eq $article.Status "published"}}✅ 已发布{{else if eq $article.Status "draft"}}📝 草稿{{else}}📦 已归档{{end}}
{{end}}
`// 文章详情模板articleDetailTemplate := `
=== 文章详情 ===
标题: {{.Title}}
作者: {{.Author.Name}} ({{.Author.Email}})
分类: {{.Category.Name}}
发布时间: {{formatDate .PublishedAt}}
更新时间: {{timeAgo .UpdatedAt}}
浏览量: {{formatNumber .ViewCount}}
点赞数: {{formatNumber .LikeCount}}标签:
{{range .Tags}}
🏷️  {{.Name}}
{{end}}内容:
{{.Content}}💬 评论 ({{len .Comments}} 条):
{{range $index, $comment := .Comments}}
{{add $index 1}}. {{$comment.Author}} ({{$comment.Likes}} 👍){{$comment.Content}}
{{end}}
`// 分类统计模板categoryStatsTemplate := `
=== 分类统计报告 ===
{{range .Categories}}
📂 {{.Name}}描述: {{.Description}}颜色: {{.Color}}文章数: {{countByCategory $.Articles .ID}}文章列表:{{range filterByCategory $.Articles .ID}}- {{.Title}} ({{formatNumber .ViewCount}} 浏览){{end}}
{{end}}📊 状态统计:
- 已发布: {{countByStatus .Articles "published"}} 篇
- 草稿: {{countByStatus .Articles "draft"}} 篇
- 已归档: {{countByStatus .Articles "archived"}} 篇
`// 作者信息模板authorProfileTemplate := `
=== 作者档案 ===
{{range .Authors}}
👤 {{.Name}}邮箱: {{.Email}}头像: {{.Avatar}}简介: {{.Bio}}发表文章:{{range $.Articles}}{{if eq .Author.ID $.ID}}- {{.Title}} ({{formatDate .PublishedAt}}){{end}}{{end}}
{{end}}
`// HTML文章卡片模板articleCardHTMLTemplate := `
<!DOCTYPE html>
<html>
<head><title>{{.Title}}</title><style>.article-card { border: 1px solid #ddd; margin: 10px; padding: 15px; border-radius: 5px; }.article-title { font-size: 1.5em; font-weight: bold; color: #333; }.article-meta { color: #666; font-size: 0.9em; margin: 5px 0; }.article-summary { margin: 10px 0; line-height: 1.6; }.article-tags { margin: 10px 0; }.tag { background: #e1f5fe; padding: 2px 8px; border-radius: 3px; margin-right: 5px; }.stats { color: #888; font-size: 0.8em; }</style>
</head>
<body><h1>{{.Title}}</h1><p>{{.Description}}</p>{{range .Articles}}<div class="article-card"><div class="article-title">{{.Title}}</div><div class="article-meta">作者: {{.Author.Name}} | 分类: {{.Category.Name}} | 发布: {{formatDate .PublishedAt}}</div><div class="article-summary">{{.Summary}}</div><div class="article-tags">{{range .Tags}}<span class="tag">{{.Name}}</span>{{end}}</div><div class="stats">👁️ {{formatNumber .ViewCount}} | 👍 {{formatNumber .LikeCount}} | 💬 {{len .Comments}}</div></div>{{end}}
</body>
</html>
`// 添加模板bts.AddTemplate("article_list", articleListTemplate, false)bts.AddTemplate("article_detail", articleDetailTemplate, false)bts.AddTemplate("category_stats", categoryStatsTemplate, false)bts.AddTemplate("author_profile", authorProfileTemplate, false)bts.AddTemplate("article_cards_html", articleCardHTMLTemplate, true)
}// DemonstrateBlogSystem 演示博客系统
func (bts *BlogTemplateSystem) DemonstrateBlogSystem() {// 创建测试数据authors := []Author{{ID: 1, Name: "张三", Email: "zhangsan@example.com", Avatar: "/avatars/zhangsan.jpg", Bio: "Go语言专家,Web开发爱好者"},{ID: 2, Name: "李四", Email: "lisi@example.com", Avatar: "/avatars/lisi.jpg", Bio: "全栈开发工程师,技术写作者"},}categories := []Category{{ID: 1, Name: "Go语言", Description: "Go语言相关技术文章", Color: "#00ADD8"},{ID: 2, Name: "Web开发", Description: "Web开发技术与实践", Color: "#FF6B6B"},{ID: 3, Name: "架构设计", Description: "软件架构设计与模式", Color: "#4ECDC4"},}tags := []Tag{{ID: 1, Name: "Go", Color: "#00ADD8"},{ID: 2, Name: "Web", Color: "#FF6B6B"},{ID: 3, Name: "模板", Color: "#4ECDC4"},{ID: 4, Name: "最佳实践", Color: "#45B7D1"},}comments := []Comment{{ID: 1, Author: "读者A", Content: "写得很好,学到了很多!", Likes: 15},{ID: 2, Author: "读者B", Content: "期待更多关于模板的内容", Likes: 8},{ID: 3, Author: "读者C", Content: "实用性很强,收藏了", Likes: 12},}articles := []Article{{ID:          1,Title:       "Go模板引擎深入解析",Content:     "本文深入探讨Go语言模板引擎的工作原理和最佳实践...",Summary:     "深入探讨Go语言模板引擎的工作原理,包括语法、函数、管道等核心概念。",Author:      authors[0],Category:    categories[0],Tags:        []Tag{tags[0], tags[2], tags[3]},Comments:    comments,PublishedAt: "2024-01-15T10:00:00Z",UpdatedAt:   "2024-01-15T15:30:00Z",ViewCount:   1250,LikeCount:   89,Status:      "published",},{ID:          2,Title:       "Web开发最佳实践指南",Content:     "本文总结了Web开发中的常见模式和最佳实践...",Summary:     "总结Web开发中的常见模式、性能优化技巧和安全最佳实践。",Author:      authors[1],Category:    categories[1],Tags:        []Tag{tags[1], tags[3]},Comments:    comments[:2],PublishedAt: "2024-01-14T09:00:00Z",UpdatedAt:   "2024-01-14T16:45:00Z",ViewCount:   890,LikeCount:   67,Status:      "published",},{ID:          3,Title:       "微服务架构设计模式",Content:     "探讨微服务架构中的常见设计模式和实现策略...",Summary:     "探讨微服务架构中的设计模式,包括服务发现、负载均衡、容错处理等关键技术。",Author:      authors[0],Category:    categories[2],Tags:        []Tag{tags[0], tags[3]},Comments:    comments[2:],PublishedAt: "2024-01-13T14:00:00Z",UpdatedAt:   "2024-01-13T18:20:00Z",ViewCount:   2100,LikeCount:   156,Status:      "published",},}blogSite := &BlogSite{Title:       "技术博客",Description: "分享Go语言、Web开发和架构设计的技术文章",Articles:    articles,Categories:  categories,Tags:        tags,Authors:     authors,Stats: map[string]int{"总文章数": len(articles),"总浏览量": 4240,"总点赞数": 312,"总评论数": 8,},Config: map[string]string{"theme":    "light","language": "zh-CN","timezone": "Asia/Shanghai",},}bts.SetupBlogTemplates()// 演示各种模板templates := []struct {name   stringisHTML bool}{{"article_list", false},{"article_detail", false},{"category_stats", false},{"author_profile", false},{"article_cards_html", true},}for _, tmpl := range templates {fmt.Printf("\n" + strings.Repeat("=", 70))fmt.Printf("\n%s 模板结果 (%s)", tmpl.name, map[bool]string{true: "HTML", false: "文本"}[tmpl.isHTML])fmt.Printf("\n" + strings.Repeat("=", 70) + "\n")var data interface{}if tmpl.name == "article_detail" {data = articles[0] // 使用第一篇文章作为详情示例} else {data = blogSite}result, err := bts.ExecuteTemplate(tmpl.name, data, tmpl.isHTML)if err != nil {fmt.Printf("执行模板失败: %v\n", err)continue}fmt.Print(result)}
}// 主函数演示
func main() {fmt.Println("=== Go Web 编程快速入门 · 07 - 模板(1):语法与最佳实践 ===\n")// 1. 安全性演示fmt.Println("1. 模板安全性演示")fmt.Println(strings.Repeat("-", 50))securityDemo := NewSecurityDemo()securityDemo.DemonstrateEscaping()// 2. 数据访问演示fmt.Println("\n\n2. 数据访问演示")fmt.Println(strings.Repeat("-", 50))dataDemo := NewDataAccessDemo()dataDemo.DemonstrateDataAccess()// 3. 条件控制演示fmt.Println("\n\n3. 条件控制演示")fmt.Println(strings.Repeat("-", 50))conditionalDemo := NewConditionalDemo()conditionalDemo.DemonstrateConditionals()// 4. 循环控制演示fmt.Println("\n\n4. 循环控制演示")fmt.Println(strings.Repeat("-", 50))loopDemo := NewLoopDemo()loopDemo.DemonstrateLoops()// 5. 内置函数演示fmt.Println("\n\n5. 内置函数演示")fmt.Println(strings.Repeat("-", 50))builtinDemo := NewBuiltinFunctionDemo()builtinDemo.DemonstrateBuiltinFunctions()// 6. 自定义函数演示fmt.Println("\n\n6. 自定义函数演示")fmt.Println(strings.Repeat("-", 50))customDemo := NewCustomFunctionDemo()customDemo.DemonstrateCustomFunctions()// 7. 博客系统综合演示fmt.Println("\n\n7. 博客系统综合演示")fmt.Println(strings.Repeat("-", 50))blogSystem := NewBlogTemplateSystem()blogSystem.DemonstrateBlogSystem()
}

5. 模板最佳实践

5.1 性能优化

  1. 模板预编译:在应用启动时预编译所有模板,避免运行时解析
  2. 模板缓存:缓存已解析的模板,避免重复解析
  3. 数据预处理:在模板执行前预处理数据,减少模板中的复杂计算
  4. 合理使用函数:避免在模板中进行复杂的数据处理

5.2 安全考虑

  1. 选择合适的模板包:Web应用使用html/template,确保自动转义
  2. 验证用户输入:对用户提供的模板内容进行严格验证
  3. 限制模板功能:避免在模板中暴露敏感的系统功能
  4. 内容安全策略:配合CSP头部增强安全性

5.3 代码组织

  1. 模板分离:将模板文件与Go代码分离,便于维护
  2. 模块化设计:使用模板继承和包含机制,提高复用性
  3. 命名规范:采用一致的模板命名规范
  4. 文档完善:为复杂模板提供详细的使用文档

5.4 错误处理

  1. 优雅降级:模板执行失败时提供备用方案
  2. 详细日志:记录模板执行过程中的错误信息
  3. 用户友好:向用户展示友好的错误信息
  4. 监控告警:对模板错误进行监控和告警

总结

本章深入探讨了Go模板系统的语法基础和最佳实践:

  1. 模板系统概述:了解了text/templatehtml/template的区别,掌握了模板安全性的重要性
  2. 语法基础:掌握了变量访问、条件控制、循环控制等核心语法
  3. 函数系统:学习了内置函数的使用和自定义函数的实现
  4. 综合实践:通过博客系统项目,将所学知识融会贯通
  5. 最佳实践:了解了性能优化、安全考虑、代码组织等实践经验

下一章我们将深入探讨Go Web 编程快速入门 · 07.2 - 模板(2):解析与执行(含Demo),学习模板的解析机制、执行流程和高级特性。反反复复烦烦烦烦烦烦烦烦烦烦烦烦烦烦烦

http://www.dtcms.com/a/524032.html

相关文章:

  • 聊城网站建设信息兴义网站建设网站建设
  • 今年前三季度浙江进出口总值首破四万亿元
  • 【一文了解】八大排序-插入排序、希尔排序
  • n8n数据存储在postgres
  • 数据结构——冒泡排序
  • 医疗连续体机器人模块化控制界面设计(2025年更新版Python库)
  • 做网站服务器需要系统wordpress折腾怕了
  • 022数据结构之树状数组——算法备赛
  • 从 TypeScript 到 Java(4):访问修饰符与作用域 —— Java 的封装哲学
  • 做网站要有什么团队上海网站营销推广
  • 残差网络的介绍及ResNet-18的搭建(pytorch版)
  • WPF绘制界面常用功能
  • vbs笔记 【未完更】
  • 不用服务器也能搭博客!Docsify+cpolar的极简方案
  • 一文了解开源大语言模型文件结构,以 Hugging Face DeepSeek-V3.1 模型仓库为例
  • 艾体宝洞察 | CRA 合规冲刺指南:艾体宝 ONEKEY 独家报告首发,洞察全球企业合规进度!
  • 网站设计方法常州网站制作维护
  • iOS 26 App 开发阶段性能优化 从多工具协作到数据驱动的实战体系
  • Nginx 配置解析与性能优化
  • vLLM 性能优化实战:批处理、量化与缓存配置方案
  • 【前端】前端浏览器性能优化的小方法
  • google广告联盟网站服务平台型网站
  • Android GPU的RenderThread Texture upload上传Bitmap优化prepareToDraw
  • 10.1 网络规划与设计——结构化布线系统
  • 国产麒麟、uos在线编辑数据库中的文件
  • 从零开始的C++学习生活 15:哈希表的使用和封装unordered_map/set
  • 【图像处理基石】通过立体视觉重建建筑高度:原理、实操与代码实现
  • 金融培训网站源码国内可以做的国外兼职网站
  • 东莞网站设计制作网站个人网页设计需求分析
  • 率先发布!浙人医基于KingbaseES构建多院区异构多活容灾新架构