必须区分静态文件服务与HTML模板渲染:静态资源用r.StaticFS嵌入static/目录,模板渲染用r.LoadHTMLGlob加载templates/下.html文件,且路由注册须先模板后静态,否则StaticFS会拦截模板请求导致404或语法不解析。

要在Go-Zero项目中让浏览器能直接访问index.html、style.css、script.js等前端资源,同时又支持{{.Title}}这类Go模板语法的动态渲染,必须区分两种完全不同的服务路径——静态文件走http.FileServer,模板渲染走LoadHTMLGlob,混用会导致404或语法不解析。
启用静态文件服务(嵌入式)
使用go-zero v1.8.4+版本时,优先采用embed.FS内嵌方式。在main.go同级目录新建static/文件夹,把所有CSS、JS、图片等放进去。
在main.go中导入embed包:import _ "embed"。
添加嵌入声明:【//go:embed static/*】
var staticFS embed.FS
初始化路由时调用r.StaticFS("/static", http.FS(staticFS)),此时访问/static/js/app.js即可命中。
注意:embed.FS路径必须是相对main.go的完整路径,不能写成"./static"或"static/"以外的形式,否则编译时报错且无提示。
启用HTML模板渲染(非嵌入)
仅当需要执行Go模板语法(如{{.Name}}、{{range .Items}})时才启用此路径。模板文件必须放在templates/目录下,且该目录不能与static/混用。
方法一:使用r.LoadHTMLGlob("templates/**/*")一次性加载所有HTML文件。
方法二:若模板分散在子目录(如templates/admin/index.html),改用r.LoadHTMLFiles("templates/base.html", "templates/admin/index.html")显式列出。
启动后调用c.HTML(200, "admin/index.html", map[string]interface{}{"Name": "GoZero"})才能触发渲染,直接访问/admin/index.html会返回原始未解析文本。
避免常见冲突配置
第一步:确认你的路由注册顺序——必须先调用r.LoadHTMLGlob(),再调用r.StaticFS(),否则StaticFS会拦截所有以/开头的请求,导致HTML模板无法被识别为模板而直接返回源码。
第二步:检查模板文件扩展名。go-zero只识别以.html结尾的文件为可渲染模板,【templates/dashboard.htm不会被加载】,哪怕它内容完全合法。
第三步:删除所有手动写的http.HandlerFunc去读取HTML文件。这种写法绕过go-zero的模板引擎,{{.X}}永远原样输出,且缺失自动Content-Type和缓存头。
第四步:不要在HTML模板里写绝对路径引用静态资源,例如是正确写法;写成会导致404,因为模板渲染不改变资源路径解析逻辑。


















