最佳实践:如何将资产嵌入到文件树中?

6

我的项目当前的结构是把 HTML 模板放在项目根目录下的 templates/ 目录中。

我的 HTTP 请求处理程序位于文件系统树的较深层级。

go.mod
templates/webpp/*.html
templates/admin-dashboard/*html
cmd/webapp/main.go
cmd/admin-dashboard/main.go
app/webapp/handlers/handler.go

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

或者

///go:embed $PROJECT_ROOT/templates

不幸的是,这些方法都不存在。go doc embed指出:

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

我可以重新定位模板(但我不想这么做,因为在某些模式下,我的Web应用程序需要相对于运行的二进制文件查看它们)。例如:

webapp            <-- binary uses templates at runtime
templates/*.html  <-- editable HTML files

因此,我可以让我的构建脚本在编译之前将它们复制到指定位置,但这似乎过于繁琐; 如果我绕过构建脚本,或者忘记或混淆了构建顺序,我可能会得到一个嵌入了v1“旧模板”的v2二进制文件。

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

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

go:embed是一个很棒的功能,但感觉我被迫使用它- 不管是强制复制、重定位、将我的模板集分解为不同的目录,还是调整我的应用程序以使用依赖项注入。

最佳实践是什么?


4
你的模板文件夹应该存在于一个Go包中,且该包应将文件夹嵌入到一个导出变量中。如果其他包需要访问这些文件,它们应该导入该原始包以访问它们。 - undefined
1
不清楚的是,为什么将go:embed指令移动到模板目录中会导致依赖注入。你可以以完全相同的方式使用它。唯一改变的是你需要添加一个额外的导入语句,并且FS值现在是包限定的。 - undefined
1
最佳做法是什么?保持简单。 - user4466350
1个回答

0
根据Hymns for Disco提到的,您可能希望通过在目录中添加一个go文件来将templates作为一个模块,以抽象访问模板并使用//go:embed: *html语法。或者,您可以将实际的模板移动到下一级并使用//go:embed templates
不幸的是,最近的Go博客文章"Organizing a Go module"并没有真正涉及到支持文件,但有人可能会认为这样做的“正确”方式是在/internal中创建一个名为/internal/fs的包,您的模板将位于/internal/fs/templates中。
我将在项目顶部以下的一个目录中继续使用一个示例,该目录名为/web。这种方法旨在在开发模式下从磁盘中读取文件,或者在生产环境中从嵌入的文件系统中读取文件。结构如下:
    ./web
    ├── fs.go
    ├── fs_test.go
    ├── static
    │   ├── favicon.svg
    │   ├── htmx.min.js
    │   └── hyperscript.js
    └── templates
        ├── home.html
        └── partial-report.html

fs.go可以像这样嵌入文件:
//go:embed templates
var templatesFS embed.FS

//go:embed static
var StaticFS embed.FS

可以使用嵌入式文件系统或者使用os.DirFS直接访问文件系统。然而,我发现一个奇怪的问题是它们挂载在不同的级别上。嵌入式模式将"static"挂载在.,而os.DirFS将其挂载在./static/,例如。
在嵌入式模式下使用fs.Sub(StaticFS, "static")允许将文件系统和嵌入式模式都挂载在"static"上。请参考timeaway的示例。

我们仍然应该被允许指向我们想要的任何路径。我最终将我的资源目录放在与main.go相同的级别上,然后传递embed.FS - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接