tmpl, err = tmpl.New("page_content").Parse(fmt.Sprintf(`{{template "%s" .}}`, contentBlockName)) |
- 创建新块:
tmpl.New("page_content"):在模板对象tmpl中定义一个新的、名为"page_content"的块。- 这个块是动态的,之前并不存在,是运行时根据传入的
contentBlockName创建的。
- 填充内容:
Parse(fmt.Sprintf({{template "%s" .}}, contentBlockName)):- 使用
fmt.Sprintf生成一个模板指令:{{template "home_content" .}}。 - 这个指令表示:在当前模板上下文中,渲染名为
home_content的块,并将当前数据(.)传递给它。
- 使用
- 换句话说,
home_content块的内容会被插入到page_content块中。
- 动态替换:
- 假设基础模板
base.html中包含:<body>{{template "page_content" .}}</body> - 在执行模板时,
page_content块会被替换为home_content块的内容。
- 假设基础模板
为什么复制模板
- 避免污染原始模板:
- 如果不克隆模板,而是直接修改原始模板,会影响后续的模板调用。
- 例如,如果在一次请求中动态定义了
page_content块,其他请求可能也会无意中使用这个定义,导致逻辑混乱。
- 支持并发调用:
- 在高并发场景中,多个请求可能同时调用
renderTemplate函数。 - 每个请求都需要一个独立的模板实例,以避免数据竞争和冲突。
- 在高并发场景中,多个请求可能同时调用
整体流程
- 模板加载:
- 加载基础模板(
base.html)和页面模板(如home.html)。 - 页面模板中定义了具体的块(如
home_content)。
- 加载基础模板(
- 动态块定义:
- 克隆模板对象,创建一个新的块(如
page_content)。 - 动态填充这个块的内容,指向传入的
contentBlockName(如home_content)。
- 克隆模板对象,创建一个新的块(如
- 模板渲染:
- 使用基础模板
base.html进行渲染。 - 在渲染过程中,
page_content块会被替换为home_content块的内容,最终填充到HTML页面的<body>区域。
- 使用基础模板
总结
通过动态创建和填充块,这种方法实现了模板的灵活性和可复用性:
- 灵活性:可以根据不同的请求动态渲染不同的内容块。
- 可复用性:基础模板保持不变,页面模板可以定义多个块,按需替换。
这种设计模式在需要动态生成HTML页面的Web应用中非常常见,能够有效提升开发效率和代码可维护性。
