如何在go embed中包含有下划线(_)的文件 + Gin SPA
tl;dr
使用 all标题来解决问题。
related issue: go@issue43854
//go:embed public
var fs embed.FS
过程
今天在尝试用go embed来提供前端文件的时候遇到了一个问题,有些文件就是加载不出来。

我用了这个函数尝试获取所有文件,看看到底是哪里出了问题
func getAllFilenames(fs *embed.FS, dir string) (out []string, err error) {
if len(dir) == 0 {
dir = "."
}
entries, err := fs.ReadDir(dir)
if err != nil {
return nil, err
}
for _, entry := range entries {
fp := path.Join(dir, entry.Name())
if entry.IsDir() {
res, err := getAllFilenames(fs, fp)
if err != nil {
return nil, err
}
out = append(out, res...)
continue
}
out = append(out, fp)
}
return
}
from source
我得到了如下输出
[public/200.html public/404.html public/admin/credential/index.html public/admin/login/index.html public/admin/panel/index.html public/favicon.ico public/index.html public/search/answer/index.html public/search/article/index.html] <nil>
发现任何在_nuxt文件夹下的文件都不在里面。于是我猜测go embed默认不会包含开头为_的文件或者文件夹
经过搜索,果然发现了解决方案。
https://github.com/golang/go/issues/43854
使用all即可
//go:embed all:pattern
Gin Gingle Page Application
solution
type GinSPA struct {
sgin.CommonApp
fsEmbed fs.ReadFileFS
}
func NewGinSPA(fsEmbed *embed.FS, fsPrefix string) *GinSPA {
fsys, err := fs.Sub(fsEmbed, fsPrefix)
if err != nil {
panic(err)
}
return &GinSPA{
fsEmbed: fsys.(fs.ReadFileFS),
}
}
func (g *GinSPA) Create(engine *gin.Engine, router gin.IRouter) error {
engine.NoRoute(g.handleSpa)
return nil
}
func (g *GinSPA) handleSpa(c *gin.Context) {
path := c.Request.URL.Path
if len(path) > 0 {
path = path[1:]
}
if data, err := g.fsEmbed.ReadFile(path); err == nil {
c.Data(200, mime.TypeByExtension(filepath.Ext(path)), data)
return
}
if data, err := g.fsEmbed.ReadFile("index.html"); err != nil {
c.String(404, "404 Not Found")
} else {
c.Data(200, mime.TypeByExtension(".html"), data)
}
}