去提问»
提问背景 Question:
大概明白你的意思了,我以为你要用<script src=/xxx></script> 来显示聊天内容呢

Go+前端历史对话渲染方案

发布时间:2026-08-19 16:12 👁️ 阅读:0

是的,完全不需要额外的 <script src="/xxx"></script> 加载。我们是通过 Go 的模板引擎,把历史对话的结构体切片直接 Marshal 成 JSON 字符串,像写普通 JS 变量一样,直接印在 HTML 的 <script> 标签里

这样,浏览器在解析 HTML 的时候,就已经把这段数据作为内存中的 JS 数组准备好了。接着我们只需要用一段极简的 JS 遍历它,调用你写好的 appendMessage 即可,所有的样式、Markdown 解析、代码块复制按钮都将 100% 完美复用

第一步:修改你的 Go 渲染后端

为了避免 Go 的 html/template 模板安全机制把 JSON 中的引号转义成 &#34;&quot;,你需要在 Go 代码里把序列化后的 JSON 字符串转换为 template.JS 类型:

import (
    "encoding/json"
    "html/template"
)

type ChatMessage struct {
    Role     string `json:"role"`     // "user" 或 "ai"
    Text     string `json:"text"`     // 消息内容
    Provider string `json:"provider"` // AI 通道,可为空
}

func ChatHandler(w http.ResponseWriter, r *http.Request) {
    // 1. 获取登录用户的历史聊天记录(从数据库读取)
    var historyList []ChatMessage
    // historyList = db.GetHistoryForUser(userID) 
    // 假设得到: [{Role: "user", Text: "你好"}, {Role: "ai", Text: "你好!我是AI。", Provider: "Gemini"}]

    // 2. 序列化为 JSON 字节
    jsonBytes, err := json.Marshal(historyList)
    if err != nil {
        jsonBytes = []byte("[]")
    }

    data := map[string]interface{}{
        "CHAT_UNIT":   "gemini",
        // 🌟 重点:转换为 template.JS 防止模板引擎破坏 JSON 结构
        "HistoryJSON": template.JS(jsonBytes), 
    }

    tmpl.Execute(w, data)
}

第二步:完整的 HTML/JS 模板(直接替换原文件)

下面是为你改造好的完整代码。核心改动点在最下方的 DOMContentLoaded 初始化区域。如果 HistoryJSON 为空或没有数据,会自动降级显示你精美撰写的 【欢迎与使用帮助】 气泡:

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
    />
    <title>百问百答 - AI Chat</title>
    <meta
      name="description"
      content="BBSGOOD 百问百答:您的全能智能助手。无论解答学习疑问、翻译全球语言,还是寻找日常美食菜谱,这里都能为您一站式搞定。融合 AI 与社区智慧,轻松服务您的品质生活。"
    />
    <link rel=