Go Web 编程快速入门 07.4 - 模板(4):组合模板与逻辑控制

1. 模板继承与布局系统

1.1 模板继承核心系统

go 复制代码
package main

import (
    "fmt"
    "html/template"
    "strings"
    "sync"
    "time"
    "path/filepath"
    "io/ioutil"
    "errors"
)

// TemplateInheritance 模板继承系统
type TemplateInheritance struct {
    // 布局模板存储
    layouts map[string]*template.Template
    // 模板构建器
    builder *TemplateBuilder
    // 缓存管理器
    cache *TemplateCache
    // 性能监控器
    monitor *PerformanceMonitor
    
    mutex sync.RWMutex
}

// LayoutConfig 布局配置
type LayoutConfig struct {
    Name        string            // 布局名称
    Path        string            // 布局文件路径
    Blocks      []string          // 定义的块名称
    Extends     string            // 继承的父布局
    Variables   map[string]string // 布局变量
    Metadata    map[string]interface{} // 元数据
}

// TemplateBuilder 模板构建器
type TemplateBuilder struct {
    baseDir     string
    funcMap     template.FuncMap
    layouts     map[string]*LayoutConfig
    partials    map[string]string
    cache       bool
    
    mutex sync.RWMutex
}

// NewTemplateInheritance 创建模板继承系统
func NewTemplateInheritance(baseDir string) *TemplateInheritance {
    return &TemplateInheritance{
        layouts: make(map[string]*template.Template),
        builder: NewTemplateBuilder(baseDir),
        cache:   NewTemplateCache(),
        monitor: NewPerformanceMonitor(),
    }
}

// NewTemplateBuilder 创建模板构建器
func NewTemplateBuilder(baseDir string) *TemplateBuilder {
    return &TemplateBuilder{
        baseDir:  baseDir,
        funcMap:  make(template.FuncMap),
        layouts:  make(map[string]*LayoutConfig),
        partials: make(map[string]string),
        cache:    true,
    }
}

// RegisterLayout 注册布局模板
func (ti *TemplateInheritance) RegisterLayout(config *LayoutConfig) error {
    ti.mutex.Lock()
    defer ti.mutex.Unlock()
    
    // 验证布局配置
    if err := ti.validateLayout(config); err != nil {
        return fmt.Errorf("布局验证失败: %w", err)
    }
    
    // 构建模板
    tmpl, err := ti.builder.BuildLayout(config)
    if err != nil {
        return fmt.Errorf("构建布局失败: %w", err)
    }
    
    ti.layouts[config.Name] = tmpl
    
    return nil
}

// validateLayout 验证布局配置
func (ti *TemplateInheritance) validateLayout(config *LayoutConfig) error {
    if config.Name == "" {
        return errors.New("布局名称不能为空")
    }
    
    if config.Path == "" {
        return errors.New("布局路径不能为空")
    }
    
    // 检查文件是否存在
    fullPath := filepath.Join(ti.builder.baseDir, config.Path)
    if _, err := ioutil.ReadFile(fullPath); err != nil {
        return fmt.Errorf("布局文件不存在: %s", fullPath)
    }
    
    // 检查继承关系
    if config.Extends != "" {
        if _, exists := ti.layouts[config.Extends]; !exists {
            return fmt.Errorf("父布局不存在: %s", config.Extends)
        }
    }
    
    return nil
}

// SetupBaseLayouts 设置基础布局
func (ti *TemplateInheritance) SetupBaseLayouts() error {
    // 主布局
    mainLayout := &LayoutConfig{
        Name: "main",
        Path: "layouts/main.html",
        Blocks: []string{"title", "head", "content", "scripts"},
        Variables: map[string]string{
            "charset": "UTF-8",
            "lang":    "zh-CN",
        },
    }
    
    // 管理后台布局
    adminLayout := &LayoutConfig{
        Name:    "admin",
        Path:    "layouts/admin.html",
        Extends: "main",
        Blocks:  []string{"sidebar", "content", "footer"},
        Variables: map[string]string{
            "theme": "admin-dark",
        },
    }
    
    // 移动端布局
    mobileLayout := &LayoutConfig{
        Name:    "mobile",
        Path:    "layouts/mobile.html",
        Extends: "main",
        Blocks:  []string{"header", "content", "navigation"},
        Variables: map[string]string{
            "viewport": "width=device-width, initial-scale=1",
        },
    }
    
    // 注册布局
    layouts := []*LayoutConfig{mainLayout, adminLayout, mobileLayout}
    for _, layout := range layouts {
        if err := ti.RegisterLayout(layout); err != nil {
            return err
        }
    }
    
    return nil
}

// BuildLayout 构建布局模板
func (tb *TemplateBuilder) BuildLayout(config *LayoutConfig) (*template.Template, error) {
    tb.mutex.Lock()
    defer tb.mutex.Unlock()
    
    // 读取布局文件
    fullPath := filepath.Join(tb.baseDir, config.Path)
    content, err := ioutil.ReadFile(fullPath)
    if err != nil {
        return nil, fmt.Errorf("读取布局文件失败: %w", err)
    }
    
    // 创建模板
    tmpl := template.New(config.Name).Funcs(tb.funcMap)
    
    // 处理继承
    if config.Extends != "" {
        parentConfig, exists := tb.layouts[config.Extends]
        if !exists {
            return nil, fmt.Errorf("父布局不存在: %s", config.Extends)
        }
        
        // 合并父布局内容
        content = tb.mergeLayouts(parentConfig, config, content)
    }
    
    // 解析模板
    tmpl, err = tmpl.Parse(string(content))
    if err != nil {
        return nil, fmt.Errorf("解析模板失败: %w", err)
    }
    
    // 缓存布局配置
    tb.layouts[config.Name] = config
    
    return tmpl, nil
}

// mergeLayouts 合并布局
func (tb *TemplateBuilder) mergeLayouts(parent, child *LayoutConfig, childContent []byte) []byte {
    // 简化的布局合并逻辑
    // 实际应用中需要更复杂的模板解析和合并
    
    parentPath := filepath.Join(tb.baseDir, parent.Path)
    parentContent, err := ioutil.ReadFile(parentPath)
    if err != nil {
        return childContent
    }
    
    // 合并变量
    mergedVars := make(map[string]string)
    for k, v := range parent.Variables {
        mergedVars[k] = v
    }
    for k, v := range child.Variables {
        mergedVars[k] = v
    }
    
    // 替换变量占位符
    result := string(parentContent)
    for key, value := range mergedVars {
        placeholder := fmt.Sprintf("{{.%s}}", key)
        result = strings.ReplaceAll(result, placeholder, value)
    }
    
    // 插入子模板内容
    contentPlaceholder := "{{block \"content\" .}}{{end}}"
    result = strings.ReplaceAll(result, contentPlaceholder, string(childContent))
    
    return []byte(result)
}

// AddFunction 添加模板函数
func (tb *TemplateBuilder) AddFunction(name string, fn interface{}) {
    tb.mutex.Lock()
    defer tb.mutex.Unlock()
    tb.funcMap[name] = fn
}

// SetCacheEnabled 设置缓存启用状态
func (tb *TemplateBuilder) SetCacheEnabled(enabled bool) {
    tb.mutex.Lock()
    defer tb.mutex.Unlock()
    tb.cache = enabled
}

1.2 部分模板管理系统

go 复制代码
// PartialManager 部分模板管理器
type PartialManager struct {
    partials map[string]*PartialTemplate
    baseDir  string
    funcMap  template.FuncMap
    
    mutex sync.RWMutex
}

// PartialTemplate 部分模板
type PartialTemplate struct {
    Name        string
    Path        string
    Content     string
    Dependencies []string
    CacheKey    string
    LastModified time.Time
    Metadata    map[string]interface{}
}

// NewPartialManager 创建部分模板管理器
func NewPartialManager(baseDir string) *PartialManager {
    return &PartialManager{
        partials: make(map[string]*PartialTemplate),
        baseDir:  baseDir,
        funcMap:  make(template.FuncMap),
    }
}

// RegisterPartial 注册部分模板
func (pm *PartialManager) RegisterPartial(name, path string) error {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    
    fullPath := filepath.Join(pm.baseDir, path)
    content, err := ioutil.ReadFile(fullPath)
    if err != nil {
        return fmt.Errorf("读取部分模板失败: %w", err)
    }
    
    // 获取文件信息
    fileInfo, err := ioutil.Stat(fullPath)
    if err != nil {
        return fmt.Errorf("获取文件信息失败: %w", err)
    }
    
    partial := &PartialTemplate{
        Name:         name,
        Path:         path,
        Content:      string(content),
        Dependencies: pm.extractDependencies(string(content)),
        CacheKey:     pm.generateCacheKey(name, path),
        LastModified: fileInfo.ModTime(),
        Metadata:     make(map[string]interface{}),
    }
    
    pm.partials[name] = partial
    
    return nil
}

// extractDependencies 提取依赖关系
func (pm *PartialManager) extractDependencies(content string) []string {
    var dependencies []string
    
    // 查找模板引用 {{template "name" .}}
    templatePattern := `{{template\s+"([^"]+)"`
    re := regexp.MustCompile(templatePattern)
    matches := re.FindAllStringSubmatch(content, -1)
    
    for _, match := range matches {
        if len(match) > 1 {
            dependencies = append(dependencies, match[1])
        }
    }
    
    return dependencies
}

// generateCacheKey 生成缓存键
func (pm *PartialManager) generateCacheKey(name, path string) string {
    return fmt.Sprintf("partial:%s:%s", name, path)
}

// SetupCommonPartials 设置常用部分模板
func (pm *PartialManager) SetupCommonPartials() error {
    commonPartials := map[string]string{
        "pagination":  "partials/pagination.html",
        "breadcrumb":  "partials/breadcrumb.html",
        "article_card": "partials/article_card.html",
        "comment":     "partials/comment.html",
        "sidebar":     "partials/sidebar.html",
        "footer":      "partials/footer.html",
        "header":      "partials/header.html",
        "navigation":  "partials/navigation.html",
    }
    
    for name, path := range commonPartials {
        if err := pm.RegisterPartial(name, path); err != nil {
            return fmt.Errorf("注册部分模板 %s 失败: %w", name, err)
        }
    }
    
    return nil
}

// GetPartial 获取部分模板
func (pm *PartialManager) GetPartial(name string) (*PartialTemplate, error) {
    pm.mutex.RLock()
    defer pm.mutex.RUnlock()
    
    partial, exists := pm.partials[name]
    if !exists {
        return nil, fmt.Errorf("部分模板不存在: %s", name)
    }
    
    return partial, nil
}

// ReloadPartial 重新加载部分模板
func (pm *PartialManager) ReloadPartial(name string) error {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    
    partial, exists := pm.partials[name]
    if !exists {
        return fmt.Errorf("部分模板不存在: %s", name)
    }
    
    fullPath := filepath.Join(pm.baseDir, partial.Path)
    content, err := ioutil.ReadFile(fullPath)
    if err != nil {
        return fmt.Errorf("重新读取部分模板失败: %w", err)
    }
    
    // 更新内容
    partial.Content = string(content)
    partial.Dependencies = pm.extractDependencies(string(content))
    partial.LastModified = time.Now()
    
    return nil
}

// TemplateComposer 模板组合器
type TemplateComposer struct {
    inheritance *TemplateInheritance
    partials    *PartialManager
    funcMap     template.FuncMap
    
    mutex sync.RWMutex
}

// NewTemplateComposer 创建模板组合器
func NewTemplateComposer(inheritance *TemplateInheritance, partials *PartialManager) *TemplateComposer {
    tc := &TemplateComposer{
        inheritance: inheritance,
        partials:    partials,
        funcMap:     make(template.FuncMap),
    }
    
    // 设置默认函数
    tc.setupDefaultFunctions()
    
    return tc
}

// setupDefaultFunctions 设置默认函数
func (tc *TemplateComposer) setupDefaultFunctions() {
    tc.funcMap["partial"] = tc.renderPartial
    tc.funcMap["block"] = tc.renderBlock
    tc.funcMap["extend"] = tc.extendLayout
    tc.funcMap["include"] = tc.includeTemplate
    tc.funcMap["yield"] = tc.yieldContent
}

// renderPartial 渲染部分模板
func (tc *TemplateComposer) renderPartial(name string, data interface{}) (template.HTML, error) {
    partial, err := tc.partials.GetPartial(name)
    if err != nil {
        return "", err
    }
    
    tmpl, err := template.New(name).Funcs(tc.funcMap).Parse(partial.Content)
    if err != nil {
        return "", fmt.Errorf("解析部分模板失败: %w", err)
    }
    
    var buf strings.Builder
    if err := tmpl.Execute(&buf, data); err != nil {
        return "", fmt.Errorf("执行部分模板失败: %w", err)
    }
    
    return template.HTML(buf.String()), nil
}

// renderBlock 渲染块
func (tc *TemplateComposer) renderBlock(name string, data interface{}) (template.HTML, error) {
    // 块渲染逻辑
    return template.HTML(fmt.Sprintf("<!-- Block: %s -->", name)), nil
}

// extendLayout 扩展布局
func (tc *TemplateComposer) extendLayout(layoutName string) (template.HTML, error) {
    // 布局扩展逻辑
    return template.HTML(fmt.Sprintf("<!-- Extend: %s -->", layoutName)), nil
}

// includeTemplate 包含模板
func (tc *TemplateComposer) includeTemplate(templateName string, data interface{}) (template.HTML, error) {
    // 模板包含逻辑
    return template.HTML(fmt.Sprintf("<!-- Include: %s -->", templateName)), nil
}

// yieldContent 输出内容
func (tc *TemplateComposer) yieldContent(blockName string) (template.HTML, error) {
    // 内容输出逻辑
    return template.HTML(fmt.Sprintf("<!-- Yield: %s -->", blockName)), nil
}

2. 模板组合与部分模板

2.1 高级逻辑控制系统

go 复制代码
// ConditionalLogic 条件逻辑控制器
type ConditionalLogic struct {
    conditions map[string]ConditionFunc
    operators  map[string]OperatorFunc
    
    mutex sync.RWMutex
}

// ConditionFunc 条件函数类型
type ConditionFunc func(interface{}) bool

// OperatorFunc 操作符函数类型
type OperatorFunc func(interface{}, interface{}) bool

// NewConditionalLogic 创建条件逻辑控制器
func NewConditionalLogic() *ConditionalLogic {
    cl := &ConditionalLogic{
        conditions: make(map[string]ConditionFunc),
        operators:  make(map[string]OperatorFunc),
    }
    
    // 设置默认条件和操作符
    cl.setupDefaultConditions()
    cl.setupDefaultOperators()
    
    return cl
}

// setupDefaultConditions 设置默认条件
func (cl *ConditionalLogic) setupDefaultConditions() {
    cl.conditions["isEmpty"] = func(v interface{}) bool {
        if v == nil {
            return true
        }
        
        switch val := v.(type) {
        case string:
            return val == ""
        case []interface{}:
            return len(val) == 0
        case map[string]interface{}:
            return len(val) == 0
        default:
            return false
        }
    }
    
    cl.conditions["isNumber"] = func(v interface{}) bool {
        switch v.(type) {
        case int, int8, int16, int32, int64:
            return true
        case uint, uint8, uint16, uint32, uint64:
            return true
        case float32, float64:
            return true
        default:
            return false
        }
    }
    
    cl.conditions["isString"] = func(v interface{}) bool {
        _, ok := v.(string)
        return ok
    }
    
    cl.conditions["isBool"] = func(v interface{}) bool {
        _, ok := v.(bool)
        return ok
    }
    
    cl.conditions["isEven"] = func(v interface{}) bool {
        if num, ok := v.(int); ok {
            return num%2 == 0
        }
        return false
    }
    
    cl.conditions["isOdd"] = func(v interface{}) bool {
        if num, ok := v.(int); ok {
            return num%2 != 0
        }
        return false
    }
}

// setupDefaultOperators 设置默认操作符
func (cl *ConditionalLogic) setupDefaultOperators() {
    cl.operators["eq"] = func(a, b interface{}) bool {
        return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
    }
    
    cl.operators["ne"] = func(a, b interface{}) bool {
        return fmt.Sprintf("%v", a) != fmt.Sprintf("%v", b)
    }
    
    cl.operators["gt"] = func(a, b interface{}) bool {
        return compareNumbers(a, b) > 0
    }
    
    cl.operators["gte"] = func(a, b interface{}) bool {
        return compareNumbers(a, b) >= 0
    }
    
    cl.operators["lt"] = func(a, b interface{}) bool {
        return compareNumbers(a, b) < 0
    }
    
    cl.operators["lte"] = func(a, b interface{}) bool {
        return compareNumbers(a, b) <= 0
    }
    
    cl.operators["contains"] = func(a, b interface{}) bool {
        aStr := fmt.Sprintf("%v", a)
        bStr := fmt.Sprintf("%v", b)
        return strings.Contains(aStr, bStr)
    }
    
    cl.operators["startsWith"] = func(a, b interface{}) bool {
        aStr := fmt.Sprintf("%v", a)
        bStr := fmt.Sprintf("%v", b)
        return strings.HasPrefix(aStr, bStr)
    }
    
    cl.operators["endsWith"] = func(a, b interface{}) bool {
        aStr := fmt.Sprintf("%v", a)
        bStr := fmt.Sprintf("%v", b)
        return strings.HasSuffix(aStr, bStr)
    }
}

// compareNumbers 比较数字
func compareNumbers(a, b interface{}) int {
    aFloat := toFloat64(a)
    bFloat := toFloat64(b)
    
    if aFloat > bFloat {
        return 1
    } else if aFloat < bFloat {
        return -1
    }
    return 0
}

// toFloat64 转换为float64
func toFloat64(v interface{}) float64 {
    switch val := v.(type) {
    case int:
        return float64(val)
    case int64:
        return float64(val)
    case float32:
        return float64(val)
    case float64:
        return val
    case string:
        if f, err := strconv.ParseFloat(val, 64); err == nil {
            return f
        }
    }
    return 0
}

// RegisterCondition 注册条件
func (cl *ConditionalLogic) RegisterCondition(name string, fn ConditionFunc) {
    cl.mutex.Lock()
    defer cl.mutex.Unlock()
    cl.conditions[name] = fn
}

// RegisterOperator 注册操作符
func (cl *ConditionalLogic) RegisterOperator(name string, fn OperatorFunc) {
    cl.mutex.Lock()
    defer cl.mutex.Unlock()
    cl.operators[name] = fn
}

// EvaluateCondition 评估条件
func (cl *ConditionalLogic) EvaluateCondition(name string, value interface{}) bool {
    cl.mutex.RLock()
    defer cl.mutex.RUnlock()
    
    if fn, exists := cl.conditions[name]; exists {
        return fn(value)
    }
    
    return false
}

// EvaluateOperator 评估操作符
func (cl *ConditionalLogic) EvaluateOperator(name string, a, b interface{}) bool {
    cl.mutex.RLock()
    defer cl.mutex.RUnlock()
    
    if fn, exists := cl.operators[name]; exists {
        return fn(a, b)
    }
    
    return false
}

// LoopControl 循环控制器
type LoopControl struct {
    iterators map[string]IteratorFunc
    filters   map[string]FilterFunc
    sorters   map[string]SorterFunc
    
    mutex sync.RWMutex
}

// IteratorFunc 迭代器函数类型
type IteratorFunc func(interface{}) []interface{}

// FilterFunc 过滤器函数类型
type FilterFunc func(interface{}) bool

// SorterFunc 排序器函数类型
type SorterFunc func([]interface{}) []interface{}

// NewLoopControl 创建循环控制器
func NewLoopControl() *LoopControl {
    lc := &LoopControl{
        iterators: make(map[string]IteratorFunc),
        filters:   make(map[string]FilterFunc),
        sorters:   make(map[string]SorterFunc),
    }
    
    // 设置默认迭代器、过滤器和排序器
    lc.setupDefaultIterators()
    lc.setupDefaultFilters()
    lc.setupDefaultSorters()
    
    return lc
}

// setupDefaultIterators 设置默认迭代器
func (lc *LoopControl) setupDefaultIterators() {
    lc.iterators["range"] = func(v interface{}) []interface{} {
        switch val := v.(type) {
        case []interface{}:
            return val
        case map[string]interface{}:
            result := make([]interface{}, 0, len(val))
            for _, value := range val {
                result = append(result, value)
            }
            return result
        case int:
            result := make([]interface{}, val)
            for i := 0; i < val; i++ {
                result[i] = i
            }
            return result
        default:
            return []interface{}{v}
        }
    }
    
    lc.iterators["chars"] = func(v interface{}) []interface{} {
        if str, ok := v.(string); ok {
            result := make([]interface{}, len(str))
            for i, char := range str {
                result[i] = string(char)
            }
            return result
        }
        return []interface{}{}
    }
    
    lc.iterators["chunk"] = func(v interface{}) []interface{} {
        // 分块迭代器,将数组分成固定大小的块
        if arr, ok := v.([]interface{}); ok {
            chunkSize := 3 // 默认块大小
            var result []interface{}
            
            for i := 0; i < len(arr); i += chunkSize {
                end := i + chunkSize
                if end > len(arr) {
                    end = len(arr)
                }
                result = append(result, arr[i:end])
            }
            
            return result
        }
        return []interface{}{}
    }
}

// setupDefaultFilters 设置默认过滤器
func (lc *LoopControl) setupDefaultFilters() {
    lc.filters["notEmpty"] = func(v interface{}) bool {
        if v == nil {
            return false
        }
        
        switch val := v.(type) {
        case string:
            return val != ""
        case []interface{}:
            return len(val) > 0
        case map[string]interface{}:
            return len(val) > 0
        default:
            return true
        }
    }
    
    lc.filters["isNumber"] = func(v interface{}) bool {
        switch v.(type) {
        case int, int8, int16, int32, int64:
            return true
        case uint, uint8, uint16, uint32, uint64:
            return true
        case float32, float64:
            return true
        default:
            return false
        }
    }
    
    lc.filters["isPositive"] = func(v interface{}) bool {
        return toFloat64(v) > 0
    }
    
    lc.filters["isNegative"] = func(v interface{}) bool {
        return toFloat64(v) < 0
    }
}

// setupDefaultSorters 设置默认排序器
func (lc *LoopControl) setupDefaultSorters() {
    lc.sorters["asc"] = func(items []interface{}) []interface{} {
        result := make([]interface{}, len(items))
        copy(result, items)
        
        sort.Slice(result, func(i, j int) bool {
            return fmt.Sprintf("%v", result[i]) < fmt.Sprintf("%v", result[j])
        })
        
        return result
    }
    
    lc.sorters["desc"] = func(items []interface{}) []interface{} {
        result := make([]interface{}, len(items))
        copy(result, items)
        
        sort.Slice(result, func(i, j int) bool {
            return fmt.Sprintf("%v", result[i]) > fmt.Sprintf("%v", result[j])
        })
        
        return result
    }
    
    lc.sorters["shuffle"] = func(items []interface{}) []interface{} {
        result := make([]interface{}, len(items))
        copy(result, items)
        
        // 简单的洗牌算法
        for i := len(result) - 1; i > 0; i-- {
            j := int(time.Now().UnixNano()) % (i + 1)
            result[i], result[j] = result[j], result[i]
        }
        
        return result
    }
}

// RegisterIterator 注册迭代器
func (lc *LoopControl) RegisterIterator(name string, fn IteratorFunc) {
    lc.mutex.Lock()
    defer lc.mutex.Unlock()
    lc.iterators[name] = fn
}

// RegisterFilter 注册过滤器
func (lc *LoopControl) RegisterFilter(name string, fn FilterFunc) {
    lc.mutex.Lock()
    defer lc.mutex.Unlock()
    lc.filters[name] = fn
}

// RegisterSorter 注册排序器
func (lc *LoopControl) RegisterSorter(name string, fn SorterFunc) {
    lc.mutex.Lock()
    defer lc.mutex.Unlock()
    lc.sorters[name] = fn
}

// Iterate 执行迭代
func (lc *LoopControl) Iterate(name string, value interface{}) []interface{} {
    lc.mutex.RLock()
    defer lc.mutex.RUnlock()
    
    if fn, exists := lc.iterators[name]; exists {
        return fn(value)
    }
    
    return []interface{}{}
}

// Filter 执行过滤
func (lc *LoopControl) Filter(items []interface{}, filterName string) []interface{} {
    lc.mutex.RLock()
    defer lc.mutex.RUnlock()
    
    if fn, exists := lc.filters[filterName]; exists {
        var result []interface{}
        for _, item := range items {
            if fn(item) {
                result = append(result, item)
            }
        }
        return result
    }
    
    return items
}

// Sort 执行排序
func (lc *LoopControl) Sort(items []interface{}, sorterName string) []interface{} {
    lc.mutex.RLock()
    defer lc.mutex.RUnlock()
    
    if fn, exists := lc.sorters[sorterName]; exists {
        return fn(items)
    }
    
    return items
}

3. 高级逻辑控制

3.1 模板缓存与性能优化

go 复制代码
// TemplateCache 模板缓存系统
type TemplateCache struct {
    strategy CacheStrategy
    config   *CacheConfig
    entries  map[string]*CacheEntry
    stats    *CacheStats
    
    mutex sync.RWMutex
}

// CacheStrategy 缓存策略
type CacheStrategy int

const (
    CacheNone CacheStrategy = iota
    CacheMemory
    CacheFile
    CacheRedis
    CacheHybrid
)

// CacheConfig 缓存配置
type CacheConfig struct {
    Strategy     CacheStrategy
    MaxSize      int64
    TTL          time.Duration
    CleanupInterval time.Duration
    RedisAddr    string
    RedisDB      int
    FileDir      string
}

// CacheEntry 缓存条目
type CacheEntry struct {
    Key        string
    Content    []byte
    Size       int64
    CreatedAt  time.Time
    AccessedAt time.Time
    AccessCount int64
    TTL        time.Duration
}

// CacheStats 缓存统计
type CacheStats struct {
    Hits        int64
    Misses      int64
    Evictions   int64
    TotalSize   int64
    EntryCount  int64
    
    mutex sync.RWMutex
}

// NewTemplateCache 创建模板缓存
func NewTemplateCache() *TemplateCache {
    config := &CacheConfig{
        Strategy:        CacheMemory,
        MaxSize:         100 * 1024 * 1024, // 100MB
        TTL:             time.Hour,
        CleanupInterval: time.Minute * 10,
    }
    
    tc := &TemplateCache{
        strategy: config.Strategy,
        config:   config,
        entries:  make(map[string]*CacheEntry),
        stats:    &CacheStats{},
    }
    
    // 启动清理协程
    go tc.startCleanup()
    
    return tc
}

// Get 获取缓存
func (tc *TemplateCache) Get(key string) ([]byte, bool) {
    tc.mutex.RLock()
    defer tc.mutex.RUnlock()
    
    entry, exists := tc.entries[key]
    if !exists {
        tc.stats.recordMiss()
        return nil, false
    }
    
    // 检查是否过期
    if tc.isExpired(entry) {
        tc.stats.recordMiss()
        return nil, false
    }
    
    // 更新访问信息
    entry.AccessedAt = time.Now()
    entry.AccessCount++
    
    tc.stats.recordHit()
    return entry.Content, true
}

// Set 设置缓存
func (tc *TemplateCache) Set(key string, content []byte, ttl time.Duration) {
    tc.mutex.Lock()
    defer tc.mutex.Unlock()
    
    // 检查是否需要清理空间
    if tc.needEviction(int64(len(content))) {
        tc.evictLRU()
    }
    
    entry := &CacheEntry{
        Key:         key,
        Content:     content,
        Size:        int64(len(content)),
        CreatedAt:   time.Now(),
        AccessedAt:  time.Now(),
        AccessCount: 1,
        TTL:         ttl,
    }
    
    // 如果键已存在,更新统计
    if oldEntry, exists := tc.entries[key]; exists {
        tc.stats.TotalSize -= oldEntry.Size
        tc.stats.EntryCount--
    }
    
    tc.entries[key] = entry
    tc.stats.TotalSize += entry.Size
    tc.stats.EntryCount++
}

// isExpired 检查是否过期
func (tc *TemplateCache) isExpired(entry *CacheEntry) bool {
    if entry.TTL <= 0 {
        return false
    }
    return time.Since(entry.CreatedAt) > entry.TTL
}

// needEviction 检查是否需要清理
func (tc *TemplateCache) needEviction(newSize int64) bool {
    return tc.stats.TotalSize+newSize > tc.config.MaxSize
}

// evictLRU 清理最少使用的条目
func (tc *TemplateCache) evictLRU() {
    if len(tc.entries) == 0 {
        return
    }
    
    var oldestKey string
    var oldestTime time.Time = time.Now()
    
    for key, entry := range tc.entries {
        if entry.AccessedAt.Before(oldestTime) {
            oldestTime = entry.AccessedAt
            oldestKey = key
        }
    }
    
    if oldestKey != "" {
        entry := tc.entries[oldestKey]
        delete(tc.entries, oldestKey)
        tc.stats.TotalSize -= entry.Size
        tc.stats.EntryCount--
        tc.stats.Evictions++
    }
}

// cleanup 清理过期条目
func (tc *TemplateCache) cleanup() {
    tc.mutex.Lock()
    defer tc.mutex.Unlock()
    
    for key, entry := range tc.entries {
        if tc.isExpired(entry) {
            delete(tc.entries, key)
            tc.stats.TotalSize -= entry.Size
            tc.stats.EntryCount--
        }
    }
}

// startCleanup 启动清理协程
func (tc *TemplateCache) startCleanup() {
    ticker := time.NewTicker(tc.config.CleanupInterval)
    defer ticker.Stop()
    
    for range ticker.C {
        tc.cleanup()
    }
}

// GetStats 获取缓存统计
func (tc *TemplateCache) GetStats() CacheStats {
    tc.stats.mutex.RLock()
    defer tc.stats.mutex.RUnlock()
    
    return *tc.stats
}

// Clear 清空缓存
func (tc *TemplateCache) Clear() {
    tc.mutex.Lock()
    defer tc.mutex.Unlock()
    
    tc.entries = make(map[string]*CacheEntry)
    tc.stats.TotalSize = 0
    tc.stats.EntryCount = 0
}

// Stop 停止缓存
func (tc *TemplateCache) Stop() {
    tc.Clear()
}

// recordHit 记录命中
func (cs *CacheStats) recordHit() {
    cs.mutex.Lock()
    defer cs.mutex.Unlock()
    cs.Hits++
}

// recordMiss 记录未命中
func (cs *CacheStats) recordMiss() {
    cs.mutex.Lock()
    defer cs.mutex.Unlock()
    cs.Misses++
}

// PerformanceMonitor 性能监控器
type PerformanceMonitor struct {
    metrics map[string]*TemplateMetrics
    alerts  map[string]*AlertConfig
    
    mutex sync.RWMutex
}

// TemplateMetrics 模板性能指标
type TemplateMetrics struct {
    Name         string
    RenderCount  int64
    TotalDuration time.Duration
    AvgDuration  time.Duration
    MaxDuration  time.Duration
    MinDuration  time.Duration
    ErrorCount   int64
    CacheHits    int64
    CacheMisses  int64
    LastRender   time.Time
}

// AlertConfig 告警配置
type AlertConfig struct {
    MaxDuration   time.Duration
    MaxErrorRate  float64
    MinCacheRate  float64
    Callback      func(*TemplateMetrics)
}

// NewPerformanceMonitor 创建性能监控器
func NewPerformanceMonitor() *PerformanceMonitor {
    return &PerformanceMonitor{
        metrics: make(map[string]*TemplateMetrics),
        alerts:  make(map[string]*AlertConfig),
    }
}

// RecordRender 记录渲染性能
func (pm *PerformanceMonitor) RecordRender(templateName string, duration time.Duration, err error) {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    
    metrics, exists := pm.metrics[templateName]
    if !exists {
        metrics = &TemplateMetrics{
            Name:        templateName,
            MinDuration: duration,
        }
        pm.metrics[templateName] = metrics
    }
    
    // 更新指标
    metrics.RenderCount++
    metrics.TotalDuration += duration
    metrics.AvgDuration = time.Duration(int64(metrics.TotalDuration) / metrics.RenderCount)
    metrics.LastRender = time.Now()
    
    if duration > metrics.MaxDuration {
        metrics.MaxDuration = duration
    }
    
    if duration < metrics.MinDuration {
        metrics.MinDuration = duration
    }
    
    if err != nil {
        metrics.ErrorCount++
    }
    
    // 检查告警
    pm.checkAlerts(templateName, metrics)
}

// RecordCacheHit 记录缓存命中
func (pm *PerformanceMonitor) RecordCacheHit(templateName string, hit bool) {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    
    metrics, exists := pm.metrics[templateName]
    if !exists {
        metrics = &TemplateMetrics{Name: templateName}
        pm.metrics[templateName] = metrics
    }
    
    if hit {
        metrics.CacheHits++
    } else {
        metrics.CacheMisses++
    }
}

// checkAlerts 检查告警
func (pm *PerformanceMonitor) checkAlerts(templateName string, metrics *TemplateMetrics) {
    alert, exists := pm.alerts[templateName]
    if !exists {
        return
    }
    
    // 检查渲染时间告警
    if alert.MaxDuration > 0 && metrics.AvgDuration > alert.MaxDuration {
        if alert.Callback != nil {
            go alert.Callback(metrics)
        }
    }
    
    // 检查错误率告警
    if alert.MaxErrorRate > 0 && metrics.RenderCount > 0 {
        errorRate := float64(metrics.ErrorCount) / float64(metrics.RenderCount)
        if errorRate > alert.MaxErrorRate {
            if alert.Callback != nil {
                go alert.Callback(metrics)
            }
        }
    }
    
    // 检查缓存命中率告警
    if alert.MinCacheRate > 0 {
        totalCache := metrics.CacheHits + metrics.CacheMisses
        if totalCache > 0 {
            cacheRate := float64(metrics.CacheHits) / float64(totalCache)
            if cacheRate < alert.MinCacheRate {
                if alert.Callback != nil {
                    go alert.Callback(metrics)
                }
            }
        }
    }
}

// GetMetrics 获取指定模板的性能指标
func (pm *PerformanceMonitor) GetMetrics(templateName string) *TemplateMetrics {
    pm.mutex.RLock()
    defer pm.mutex.RUnlock()
    
    if metrics, exists := pm.metrics[templateName]; exists {
        // 返回副本
        result := *metrics
        return &result
    }
    
    return nil
}

// GetAllMetrics 获取所有性能指标
func (pm *PerformanceMonitor) GetAllMetrics() map[string]*TemplateMetrics {
    pm.mutex.RLock()
    defer pm.mutex.RUnlock()
    
    result := make(map[string]*TemplateMetrics)
    for name, metrics := range pm.metrics {
        // 返回副本
        result[name] = &TemplateMetrics{
            Name:          metrics.Name,
            RenderCount:   metrics.RenderCount,
            TotalDuration: metrics.TotalDuration,
            AvgDuration:   metrics.AvgDuration,
            MaxDuration:   metrics.MaxDuration,
            MinDuration:   metrics.MinDuration,
            ErrorCount:    metrics.ErrorCount,
            CacheHits:     metrics.CacheHits,
            CacheMisses:   metrics.CacheMisses,
            LastRender:    metrics.LastRender,
        }
    }
    
    return result
}

// SetAlertThreshold 设置告警阈值
func (pm *PerformanceMonitor) SetAlertThreshold(templateName string, config *AlertConfig) {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    pm.alerts[templateName] = config
}

// PrintReport 打印性能报告
func (pm *PerformanceMonitor) PrintReport() {
    pm.mutex.RLock()
    defer pm.mutex.RUnlock()
    
    fmt.Println("=== 模板性能报告 ===")
    fmt.Printf("%-20s %-10s %-15s %-15s %-15s %-10s %-10s\n", 
        "模板名称", "渲染次数", "平均耗时", "最大耗时", "最小耗时", "错误数", "缓存命中率")
    fmt.Println(strings.Repeat("-", 100))
    
    for _, metrics := range pm.metrics {
        totalCache := metrics.CacheHits + metrics.CacheMisses
        cacheRate := "N/A"
        if totalCache > 0 {
            cacheRate = fmt.Sprintf("%.2f%%", float64(metrics.CacheHits)/float64(totalCache)*100)
        }
        
        fmt.Printf("%-20s %-10d %-15s %-15s %-15s %-10d %-10s\n",
            metrics.Name,
            metrics.RenderCount,
            metrics.AvgDuration,
            metrics.MaxDuration,
            metrics.MinDuration,
            metrics.ErrorCount,
            cacheRate,
        )
    }
}

// Reset 重置性能指标
func (pm *PerformanceMonitor) Reset() {
    pm.mutex.Lock()
    defer pm.mutex.Unlock()
    pm.metrics = make(map[string]*TemplateMetrics)
}

4. 模板缓存与性能优化

4.1 实战项目:CMS内容管理系统

go 复制代码
// CMSSystem CMS内容管理系统
type CMSSystem struct {
    inheritance *TemplateInheritance
    partials    *PartialManager
    composer    *TemplateComposer
    cache       *TemplateCache
    monitor     *PerformanceMonitor
    conditional *ConditionalLogic
    loop        *LoopControl
    
    // 数据模型
    posts      []Post
    categories []Category
    users      []User
    tags       []Tag
    
    mutex sync.RWMutex
}

// Post 文章模型
type Post struct {
    ID          int       `json:"id"`
    Title       string    `json:"title"`
    Content     string    `json:"content"`
    Summary     string    `json:"summary"`
    AuthorID    int       `json:"author_id"`
    CategoryID  int       `json:"category_id"`
    Tags        []string  `json:"tags"`
    Status      string    `json:"status"` // draft, published, archived
    ViewCount   int       `json:"view_count"`
    CreatedAt   time.Time `json:"created_at"`
    UpdatedAt   time.Time `json:"updated_at"`
    PublishedAt *time.Time `json:"published_at,omitempty"`
}

// Category 分类模型
type Category struct {
    ID          int    `json:"id"`
    Name        string `json:"name"`
    Slug        string `json:"slug"`
    Description string `json:"description"`
    PostCount   int    `json:"post_count"`
    ParentID    *int   `json:"parent_id,omitempty"`
}

// User 用户模型
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Email    string `json:"email"`
    Name     string `json:"name"`
    Avatar   string `json:"avatar"`
    Role     string `json:"role"` // admin, editor, author
}

// Tag 标签模型
type Tag struct {
    ID        int    `json:"id"`
    Name      string `json:"name"`
    Slug      string `json:"slug"`
    PostCount int    `json:"post_count"`
}

// NewCMSSystem 创建CMS系统
func NewCMSSystem(baseDir string) *CMSSystem {
    inheritance := NewTemplateInheritance(baseDir)
    partials := NewPartialManager(baseDir)
    composer := NewTemplateComposer(inheritance, partials)
    
    cms := &CMSSystem{
        inheritance: inheritance,
        partials:    partials,
        composer:    composer,
        cache:       NewTemplateCache(),
        monitor:     NewPerformanceMonitor(),
        conditional: NewConditionalLogic(),
        loop:        NewLoopControl(),
    }
    
    // 初始化系统
    cms.initialize()
    
    return cms
}

// initialize 初始化CMS系统
func (cms *CMSSystem) initialize() error {
    // 设置基础布局
    if err := cms.inheritance.SetupBaseLayouts(); err != nil {
        return fmt.Errorf("设置基础布局失败: %w", err)
    }
    
    // 设置部分模板
    if err := cms.partials.SetupCommonPartials(); err != nil {
        return fmt.Errorf("设置部分模板失败: %w", err)
    }
    
    // 设置CMS专用模板
    if err := cms.setupCMSTemplates(); err != nil {
        return fmt.Errorf("设置CMS模板失败: %w", err)
    }
    
    // 初始化示例数据
    cms.setupSampleData()
    
    return nil
}

// setupSampleData 设置示例数据
func (cms *CMSSystem) setupSampleData() {
    // 用户数据
    cms.users = []User{
        {ID: 1, Username: "admin", Email: "admin@example.com", Name: "管理员", Role: "admin"},
        {ID: 2, Username: "editor", Email: "editor@example.com", Name: "编辑", Role: "editor"},
        {ID: 3, Username: "author", Email: "author@example.com", Name: "作者", Role: "author"},
    }
    
    // 分类数据
    cms.categories = []Category{
        {ID: 1, Name: "技术", Slug: "tech", Description: "技术相关文章", PostCount: 5},
        {ID: 2, Name: "生活", Slug: "life", Description: "生活感悟", PostCount: 3},
        {ID: 3, Name: "教程", Slug: "tutorial", Description: "教程文章", PostCount: 4},
    }
    
    // 标签数据
    cms.tags = []Tag{
        {ID: 1, Name: "Go", Slug: "go", PostCount: 8},
        {ID: 2, Name: "Web开发", Slug: "web-dev", PostCount: 6},
        {ID: 3, Name: "模板", Slug: "template", PostCount: 4},
        {ID: 4, Name: "性能优化", Slug: "performance", PostCount: 3},
    }
    
    // 文章数据
    cms.posts = []Post{
        {
            ID: 1, Title: "Go Web模板系统详解", 
            Content: "这是一篇关于Go Web模板系统的详细教程...",
            Summary: "深入了解Go Web模板系统的使用方法",
            AuthorID: 1, CategoryID: 1, Tags: []string{"Go", "Web开发", "模板"},
            Status: "published", ViewCount: 150,
            CreatedAt: time.Now().AddDate(0, 0, -7),
            UpdatedAt: time.Now().AddDate(0, 0, -1),
        },
        {
            ID: 2, Title: "模板缓存与性能优化",
            Content: "本文介绍如何优化模板渲染性能...",
            Summary: "提升模板渲染性能的实用技巧",
            AuthorID: 2, CategoryID: 3, Tags: []string{"性能优化", "模板"},
            Status: "published", ViewCount: 89,
            CreatedAt: time.Now().AddDate(0, 0, -5),
            UpdatedAt: time.Now().AddDate(0, 0, -2),
        },
        {
            ID: 3, Title: "CMS系统架构设计",
            Content: "分享CMS系统的架构设计思路...",
            Summary: "从零开始设计一个CMS系统",
            AuthorID: 3, CategoryID: 1, Tags: []string{"架构", "CMS"},
            Status: "draft", ViewCount: 0,
            CreatedAt: time.Now().AddDate(0, 0, -3),
            UpdatedAt: time.Now().AddDate(0, 0, -1),
        },
    }
}

// setupCMSTemplates 设置CMS专用模板
func (cms *CMSSystem) setupCMSTemplates() error {
    // 首页模板
    homeTemplate := &LayoutConfig{
        Name: "home",
        Path: "cms/home.html",
        Extends: "main",
        Blocks: []string{"hero", "featured", "recent", "sidebar"},
        Variables: map[string]string{
            "page_type": "home",
            "title": "首页",
        },
    }
    
    // 文章详情模板
    postTemplate := &LayoutConfig{
        Name: "post",
        Path: "cms/post.html", 
        Extends: "main",
        Blocks: []string{"content", "sidebar", "comments"},
        Variables: map[string]string{
            "page_type": "post",
        },
    }
    
    // 分类页面模板
    categoryTemplate := &LayoutConfig{
        Name: "category",
        Path: "cms/category.html",
        Extends: "main", 
        Blocks: []string{"header", "posts", "pagination"},
        Variables: map[string]string{
            "page_type": "category",
        },
    }
    
    // 管理后台首页模板
    adminDashboardTemplate := &LayoutConfig{
        Name: "admin_dashboard",
        Path: "cms/admin/dashboard.html",
        Extends: "admin",
        Blocks: []string{"stats", "recent_posts", "quick_actions"},
        Variables: map[string]string{
            "page_type": "admin_dashboard",
            "title": "管理后台",
        },
    }
    
    // 注册模板
    templates := []*LayoutConfig{
        homeTemplate, postTemplate, categoryTemplate, adminDashboardTemplate,
    }
    
    for _, tmpl := range templates {
        if err := cms.inheritance.RegisterLayout(tmpl); err != nil {
            return fmt.Errorf("注册模板 %s 失败: %w", tmpl.Name, err)
        }
    }
    
    return nil
}

// RenderHomePage 渲染首页
func (cms *CMSSystem) RenderHomePage() (string, error) {
    start := time.Now()
    
    // 检查缓存
    cacheKey := "home_page"
    if cached, found := cms.cache.Get(cacheKey); found {
        cms.monitor.RecordCacheHit("home", true)
        return string(cached), nil
    }
    cms.monitor.RecordCacheHit("home", false)
    
    // 准备数据
    data := map[string]interface{}{
        "title": "欢迎来到我们的博客",
        "featured_posts": cms.getFeaturedPosts(3),
        "recent_posts": cms.getRecentPosts(5),
        "categories": cms.categories,
        "popular_tags": cms.getPopularTags(10),
        "stats": cms.getStatistics(),
    }
    
    // 渲染模板
    tmpl, exists := cms.inheritance.layouts["home"]
    if !exists {
        return "", errors.New("首页模板不存在")
    }
    
    var buf strings.Builder
    err := tmpl.Execute(&buf, data)
    
    // 记录性能
    duration := time.Since(start)
    cms.monitor.RecordRender("home", duration, err)
    
    if err != nil {
        return "", fmt.Errorf("渲染首页失败: %w", err)
    }
    
    result := buf.String()
    
    // 缓存结果
    cms.cache.Set(cacheKey, []byte(result), time.Hour)
    
    return result, nil
}

// RenderPost 渲染文章详情
func (cms *CMSSystem) RenderPost(postID int) (string, error) {
    start := time.Now()
    
    // 检查缓存
    cacheKey := fmt.Sprintf("post_%d", postID)
    if cached, found := cms.cache.Get(cacheKey); found {
        cms.monitor.RecordCacheHit("post", true)
        return string(cached), nil
    }
    cms.monitor.RecordCacheHit("post", false)
    
    // 查找文章
    var post *Post
    for i := range cms.posts {
        if cms.posts[i].ID == postID {
            post = &cms.posts[i]
            break
        }
    }
    
    if post == nil {
        return "", errors.New("文章不存在")
    }
    
    // 准备数据
    data := map[string]interface{}{
        "post": post,
        "author": cms.getUserByID(post.AuthorID),
        "category": cms.getCategoryByID(post.CategoryID),
        "related_posts": cms.getRelatedPosts(post.ID, 3),
        "prev_post": cms.getAdjacentPosts(post.ID, "prev"),
        "next_post": cms.getAdjacentPosts(post.ID, "next"),
        "title": post.Title,
    }
    
    // 渲染模板
    tmpl, exists := cms.inheritance.layouts["post"]
    if !exists {
        return "", errors.New("文章模板不存在")
    }
    
    var buf strings.Builder
    err := tmpl.Execute(&buf, data)
    
    // 记录性能
    duration := time.Since(start)
    cms.monitor.RecordRender("post", duration, err)
    
    if err != nil {
        return "", fmt.Errorf("渲染文章失败: %w", err)
    }
    
    result := buf.String()
    
    // 缓存结果
    cms.cache.Set(cacheKey, []byte(result), time.Hour*2)
    
    return result, nil
}

// RenderCategory 渲染分类页面
func (cms *CMSSystem) RenderCategory(categoryID int, page int) (string, error) {
    start := time.Now()
    
    // 检查缓存
    cacheKey := fmt.Sprintf("category_%d_page_%d", categoryID, page)
    if cached, found := cms.cache.Get(cacheKey); found {
        cms.monitor.RecordCacheHit("category", true)
        return string(cached), nil
    }
    cms.monitor.RecordCacheHit("category", false)
    
    // 查找分类
    var category *Category
    for i := range cms.categories {
        if cms.categories[i].ID == categoryID {
            category = &cms.categories[i]
            break
        }
    }
    
    if category == nil {
        return "", errors.New("分类不存在")
    }
    
    // 准备数据
    posts := cms.getPostsByCategory(categoryID, page, 10)
    data := map[string]interface{}{
        "category": category,
        "posts": posts,
        "current_page": page,
        "total_pages": (category.PostCount + 9) / 10, // 向上取整
        "title": fmt.Sprintf("%s - 分类", category.Name),
    }
    
    // 渲染模板
    tmpl, exists := cms.inheritance.layouts["category"]
    if !exists {
        return "", errors.New("分类模板不存在")
    }
    
    var buf strings.Builder
    err := tmpl.Execute(&buf, data)
    
    // 记录性能
    duration := time.Since(start)
    cms.monitor.RecordRender("category", duration, err)
    
    if err != nil {
        return "", fmt.Errorf("渲染分类页面失败: %w", err)
    }
    
    result := buf.String()
    
    // 缓存结果
    cms.cache.Set(cacheKey, []byte(result), time.Minute*30)
    
    return result, nil
}

// RenderAdminDashboard 渲染管理后台首页
func (cms *CMSSystem) RenderAdminDashboard() (string, error) {
    start := time.Now()
    
    // 管理后台不使用缓存,确保数据实时性
    
    // 准备数据
    data := map[string]interface{}{
        "stats": cms.getStatistics(),
        "recent_posts": cms.getRecentPosts(10),
        "draft_posts": cms.getDraftPosts(),
        "categories": cms.categories,
        "users": cms.users,
        "title": "管理后台",
    }
    
    // 渲染模板
    tmpl, exists := cms.inheritance.layouts["admin_dashboard"]
    if !exists {
        return "", errors.New("管理后台模板不存在")
    }
    
    var buf strings.Builder
    err := tmpl.Execute(&buf, data)
    
    // 记录性能
    duration := time.Since(start)
    cms.monitor.RecordRender("admin_dashboard", duration, err)
    
    if err != nil {
        return "", fmt.Errorf("渲染管理后台失败: %w", err)
    }
    
    return buf.String(), nil
}

// 辅助方法

// getFeaturedPosts 获取推荐文章
func (cms *CMSSystem) getFeaturedPosts(limit int) []Post {
    var featured []Post
    count := 0
    
    for _, post := range cms.posts {
        if post.Status == "published" && post.ViewCount > 100 {
            featured = append(featured, post)
            count++
            if count >= limit {
                break
            }
        }
    }
    
    return featured
}

// getRecentPosts 获取最新文章
func (cms *CMSSystem) getRecentPosts(limit int) []Post {
    var recent []Post
    count := 0
    
    // 按创建时间倒序
    for i := len(cms.posts) - 1; i >= 0 && count < limit; i-- {
        if cms.posts[i].Status == "published" {
            recent = append(recent, cms.posts[i])
            count++
        }
    }
    
    return recent
}

// getRelatedPosts 获取相关文章
func (cms *CMSSystem) getRelatedPosts(postID int, limit int) []Post {
    var related []Post
    var currentPost *Post
    
    // 找到当前文章
    for i := range cms.posts {
        if cms.posts[i].ID == postID {
            currentPost = &cms.posts[i]
            break
        }
    }
    
    if currentPost == nil {
        return related
    }
    
    count := 0
    for _, post := range cms.posts {
        if post.ID != postID && post.Status == "published" && count < limit {
            // 简单的相关性判断:同分类或有共同标签
            if post.CategoryID == currentPost.CategoryID {
                related = append(related, post)
                count++
            }
        }
    }
    
    return related
}

// getAdjacentPosts 获取相邻文章
func (cms *CMSSystem) getAdjacentPosts(postID int, direction string) *Post {
    for i, post := range cms.posts {
        if post.ID == postID {
            if direction == "prev" && i > 0 {
                return &cms.posts[i-1]
            } else if direction == "next" && i < len(cms.posts)-1 {
                return &cms.posts[i+1]
            }
            break
        }
    }
    return nil
}

// getPostsByCategory 按分类获取文章
func (cms *CMSSystem) getPostsByCategory(categoryID, page, pageSize int) []Post {
    var posts []Post
    
    for _, post := range cms.posts {
        if post.CategoryID == categoryID && post.Status == "published" {
            posts = append(posts, post)
        }
    }
    
    // 分页
    start := (page - 1) * pageSize
    end := start + pageSize
    
    if start >= len(posts) {
        return []Post{}
    }
    
    if end > len(posts) {
        end = len(posts)
    }
    
    return posts[start:end]
}

// getDraftPosts 获取草稿文章
func (cms *CMSSystem) getDraftPosts() []Post {
    var drafts []Post
    
    for _, post := range cms.posts {
        if post.Status == "draft" {
            drafts = append(drafts, post)
        }
    }
    
    return drafts
}

// getUserByID 根据ID获取用户
func (cms *CMSSystem) getUserByID(userID int) *User {
    for i := range cms.users {
        if cms.users[i].ID == userID {
            return &cms.users[i]
        }
    }
    return nil
}

// getCategoryByID 根据ID获取分类
func (cms *CMSSystem) getCategoryByID(categoryID int) *Category {
    for i := range cms.categories {
        if cms.categories[i].ID == categoryID {
            return &cms.categories[i]
        }
    }
    return nil
}

// getAllCategories 获取所有分类
func (cms *CMSSystem) getAllCategories() []Category {
    return cms.categories
}

// getPopularTags 获取热门标签
func (cms *CMSSystem) getPopularTags(limit int) []Tag {
    // 简单返回前N个标签
    if limit > len(cms.tags) {
        limit = len(cms.tags)
    }
    return cms.tags[:limit]
}

// getStatistics 获取统计信息
func (cms *CMSSystem) getStatistics() map[string]interface{} {
    publishedCount := 0
    draftCount := 0
    totalViews := 0
    
    for _, post := range cms.posts {
        if post.Status == "published" {
            publishedCount++
            totalViews += post.ViewCount
        } else if post.Status == "draft" {
            draftCount++
        }
    }
    
    return map[string]interface{}{
        "total_posts": len(cms.posts),
        "published_posts": publishedCount,
        "draft_posts": draftCount,
        "total_categories": len(cms.categories),
        "total_tags": len(cms.tags),
        "total_users": len(cms.users),
        "total_views": totalViews,
    }
}

// RunCMSDemo 运行CMS演示
func RunCMSDemo() {
    fmt.Println("=== CMS内容管理系统演示 ===")
    
    // 创建CMS系统
    cms := NewCMSSystem("templates")
    
    // 渲染首页
    fmt.Println("\n1. 渲染首页...")
    homePage, err := cms.RenderHomePage()
    if err != nil {
        fmt.Printf("渲染首页失败: %v\n", err)
    } else {
        fmt.Printf("首页渲染成功,长度: %d 字符\n", len(homePage))
    }
    
    // 渲染文章详情
    fmt.Println("\n2. 渲染文章详情...")
    postPage, err := cms.RenderPost(1)
    if err != nil {
        fmt.Printf("渲染文章失败: %v\n", err)
    } else {
        fmt.Printf("文章渲染成功,长度: %d 字符\n", len(postPage))
    }
    
    // 渲染分类页面
    fmt.Println("\n3. 渲染分类页面...")
    categoryPage, err := cms.RenderCategory(1, 1)
    if err != nil {
        fmt.Printf("渲染分类页面失败: %v\n", err)
    } else {
        fmt.Printf("分类页面渲染成功,长度: %d 字符\n", len(categoryPage))
    }
    
    // 渲染管理后台
    fmt.Println("\n4. 渲染管理后台...")
    adminPage, err := cms.RenderAdminDashboard()
    if err != nil {
        fmt.Printf("渲染管理后台失败: %v\n", err)
    } else {
        fmt.Printf("管理后台渲染成功,长度: %d 字符\n", len(adminPage))
    }
    
    // 显示性能报告
    fmt.Println("\n5. 性能监控报告:")
    cms.monitor.PrintReport()
    
    // 显示缓存统计
    fmt.Println("\n6. 缓存统计:")
    stats := cms.cache.GetStats()
    fmt.Printf("缓存命中: %d, 未命中: %d, 命中率: %.2f%%\n", 
        stats.Hits, stats.Misses, 
        float64(stats.Hits)/float64(stats.Hits+stats.Misses)*100)
    fmt.Printf("缓存条目: %d, 总大小: %d KB\n", 
        stats.EntryCount, stats.TotalSize/1024)
}

// main 主函数演示
func main() {
    RunCMSDemo()
}

5. 实战项目:CMS内容管理系统

5.1 章节总结

本章深入探讨了Go Web模板的高级特性,包括模板继承、组合、逻辑控制和性能优化。通过构建一个完整的CMS内容管理系统,我们学习了:

核心内容回顾
  1. 模板继承与布局系统

    • 模板继承机制的设计与实现
    • 布局配置与验证系统
    • 模板构建器的灵活应用
    • 多层次布局的组合策略
  2. 部分模板管理

    • 部分模板的注册与管理
    • 依赖关系的自动解析
    • 模板组合器的统一调度
    • 常用组件的模块化设计
  3. 高级逻辑控制

    • 条件逻辑的扩展与定制
    • 循环控制的多样化实现
    • 迭代器、过滤器、排序器的组合使用
    • 模板函数的动态注册机制
  4. 缓存与性能优化

    • 多策略缓存系统设计
    • LRU算法的内存管理
    • 性能监控与告警机制
    • 缓存命中率的统计分析
  5. CMS实战项目

    • 完整的内容管理系统架构
    • 数据模型的设计与关联
    • 多页面类型的渲染策略
    • 缓存策略的差异化应用
技术特色
  • 模块化设计:每个组件都具有独立的职责和清晰的接口
  • 中文注释:所有关键代码都有详细的中文说明
  • 最佳实践:遵循Go语言的编程规范和设计模式
  • 性能优化:从缓存、监控到内存管理的全方位优化
实际应用价值
  • Web开发:为复杂的Web应用提供强大的模板支持
  • 多端适配:支持PC、移动端、管理后台的差异化布局
  • 系统集成:可以轻松集成到现有的Go Web框架中
  • 扩展性:提供了丰富的扩展点和自定义机制

5.2 下一章预告

下一章我们将学习 "Go Web 编程快速入门 · 08 - JSON API:编码、解码与内容协商",内容包括:

  1. JSON数据处理

    • 高级编码解码技术
    • 自定义类型处理器
    • 流式JSON处理
    • Schema验证机制
  2. RESTful API设计

    • API框架架构设计
    • 路由与中间件系统
    • 版本管理策略
    • 错误处理机制
  3. 内容协商

    • 多格式内容支持
    • Accept头解析
    • 响应格式自动选择
    • 压缩与编码处理
  4. 实战项目

    • 电商API系统构建
    • 商品管理接口
    • 订单处理流程
    • 性能监控与优化

通过下一章的学习,您将掌握构建高性能、可扩展的JSON API服务的完整技能栈!


本章完整代码可在项目仓库中找到,建议结合实际项目进行练习和扩展。

相关推荐
lightqjx3 小时前
【C++】list 常见使用和模拟实现
开发语言·c++
咖啡教室3 小时前
每日一个计算机小知识:MAC地址
后端·网络协议
咖啡教室3 小时前
每日一个计算机小知识:LAN和WAN
后端·网络协议
ceclar1233 小时前
C++容器queue
开发语言·c++
咖啡教室3 小时前
每日一个计算机小知识:Socket
后端·websocket
咖啡教室3 小时前
每日一个计算机小知识:DNS和hosts文件
后端·dns
IT_陈寒3 小时前
React 19重磅前瞻:10个性能优化技巧让你少写30%的useEffect代码
前端·人工智能·后端
陈皮话梅糖@3 小时前
Speckit和Claude 的初体验
开发语言·ide
咖啡教室3 小时前
每日一个计算机小知识:UDP
后端·网络协议