最佳实践:将资产嵌入文件树?

And*_*iak 6 go

我的项目当前的结构使得 HTML 模板位于项目根目录中templates/

\n

我的 HTTP 请求处理程序位于文件系统树的下几层。

\n
go.mod\ntemplates/webpp/*.html\ntemplates/admin-dashboard/*html\ncmd/webapp/main.go\ncmd/admin-dashboard/main.go\napp/webapp/handlers/handler.go\n
Run Code Online (Sandbox Code Playgroud)\n

理想情况下,我希望能够按以下方式使用 go:embed:

\n
go.mod\ntemplates/webpp/*.html\ntemplates/admin-dashboard/*html\ncmd/webapp/main.go\ncmd/admin-dashboard/main.go\napp/webapp/handlers/handler.go\n
Run Code Online (Sandbox Code Playgroud)\n

或者

\n
//go:embed ../../templates\n
Run Code Online (Sandbox Code Playgroud)\n

但不幸的是,这两种方法都不存在。这go doc embed

\n
\n

这些模式是相对于包含源文件的包\n目录进行解释的。路径分隔符是正斜杠,\n即使在 Windows 系统上也是如此。模式不能包含 \xe2\x80\x98.\xe2\x80\x99 或 \xe2\x80\x98..\xe2\x80\x99 或空路径\n元素,也不能以斜杠开头或结尾。

\n
\n

我可以重新定位模板(这是我不想做的事情,因为在某些模式下我的 web 应用程序希望看到它们相对于正在运行的二进制文件)。例如

\n
webapp            <-- binary uses templates at runtime\ntemplates/*.html  <-- editable HTML files\n
Run Code Online (Sandbox Code Playgroud)\n

所以我可以让我的构建脚本在编译之前将它们复制到位,但这似乎不必要地复杂;如果我绕过构建脚本或者忘记或搞乱构建顺序,我最终可能会得到嵌入了 v1“旧模板”的 v2 二进制文件。

\n

或者,我可以将templates/目录打包并导出embed.FS,然后将其作为依赖项注入到我的应用程序中,但现在我的代码被重新构造以适应嵌入过程。

\n

go:embed 未来是否有可能允许相对于项目根进行某种类型的嵌入,或者这会引发安全问题?

\n

go:embed 是一个很棒的功能,但感觉我对它很感激——要么被迫复制、重新定位、将我的模板集拆分到单独的目录中,要么调整我的应用程序以使用依赖项注入。

\n

最佳做法是什么?

\n

ror*_*ycl 0

正如Hymns for Disco所提到的,您可能希望templates通过在目录中添加 go 文件来创建一个模块,以抽象对模板的访问并使用//go:embed: *html语法。或者,您可以将实际模板下移一个级别并使用//go:embed templates.

\n

不幸的是,最近的 Go 博客文章“组织 Go 模块”并没有真正处理支持文件,但有些人可能会认为执行此操作的“正确”方法是在/internal调用中创建一个包,/internal/fs并且您的模板将是在/internal/fs/templates

\n

我将继续在项目顶部下面名为 的目录中提供一个示例/web。此方法旨在在开发模式下从磁盘存储文件或在生产中从嵌入式文件系统存储文件。结构如下:

\n
    ./web\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fs.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fs_test.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 static\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 favicon.svg\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 htmx.min.js\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hyperscript.js\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 templates\n     \xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 home.html\n     \xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 partial-report.html\n
Run Code Online (Sandbox Code Playgroud)\n

fs.go 可以嵌入这样的文件:

\n
    ./web\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fs.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fs_test.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 static\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 favicon.svg\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 htmx.min.js\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hyperscript.js\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 templates\n     \xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 home.html\n     \xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 partial-report.html\n
Run Code Online (Sandbox Code Playgroud)\n

然后,人们可以使用嵌入式文件系统,也可以将它们交换出来,以便使用os.DirFS. 然而,我发现一个奇怪的现象是它们安装在不同的级别。例如,嵌入模式在“静态”.位置安装,而os.DirFS在“静态”位置安装。./static/

\n

用于fs.Sub(StaticFS, "static")嵌入模式允许文件系统和嵌入模式都以“静态”方式安装。请参阅timeaway的示例。

\n