如何在go embed中包含有下划线(_)的文件 + Gin SPA

tl;dr

使用 all标题来解决问题。

related issue: go@issue43854

1
2
//go:embed public
var fs embed.FS

过程

今天在尝试用go embed来提供前端文件的时候遇到了一个问题,有些文件就是加载不出来。

image-20240215190617849

我用了这个函数尝试获取所有文件,看看到底是哪里出了问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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

我得到了如下输出

1
[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即可

1
//go:embed all:pattern

Gin Gingle Page Application

solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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)
}
}