通过 go embed.FS 将 gin 模板及静态资源文件打包进二进制程序

文章目录

    使用 gin 写网站会涉及到大量的外部文件:

    • HTML 模板文件
    • 静态资源文件:js,css,图片等
    • 多语言翻译文件

    发布时,除了要将编译好的二进制文件上传到服务器,还需要将上面提到的三类文件同步到二进制文件所在的目录。这样有两个弊端:

    • 部署麻烦
    • 如果是交付给客户,放在客户服务器上运行,客户能拿到这些文件的明文

    embed 打包

    go 1.16 引入的新特性 embed 支持将这些外部文件打包入二进制文件。

    而且 gin 也支持了 embed,配置起来就更方便了。

    首先需要过一遍 go embed 的官方文档,否则 gin 里的 embed 代码不容易理解。

    template 及 static 文件打包

    main.go

    //go:embed templates/* public/*
    var f embed.FS
    
    func main() {
    	...
    
    	r := gin.Default()
    
    	// apply i18n middleware
    	r.Use(i18n.GinI18nLocalize())
    
    	// 自定义模板函数
    	funcMap := template.FuncMap{
    		"UnescapeHTML": utils.UnescapeHTML,
    		"Localize":     ginI18n.GetMessage,
    	}
    
    	// embed files
    	tmpl := template.New("").Funcs(funcMap)
    	tmpl = template.Must(tmpl.ParseFS(f, "templates/*.html"))
    	r.SetHTMLTemplate(tmpl)
    
    	fp, _ := fs.Sub(f, "public")
    	r.StaticFS("/public", http.FS(fp))
    
    	...
    }
    

    模板函数不要忘了配置,否则会报错,例如:

    panic: template: article.html:6: function “Localize” not defined

    i18n 翻译文件打包

    i18n.go

    gin i18n 里内置了 embed 的支持,修改一下 loader 即可。

    注意,对于 sub package 中的 embed directive,路径是相对于代码文件的,而不是项目根目录。
    例如,i18n.go 平级下有个 lang 目录,里面存放了翻译文件。

    import (
    	"embed"
    	ginI18n "github.com/gin-contrib/i18n"
    )
    
    //go:embed lang/*
    var fs embed.FS
    
    func GinI18nLocalize() gin.HandlerFunc {
    	return ginI18n.Localize(
    		ginI18n.WithBundle(&ginI18n.BundleCfg{
    			RootPath:         "./lang",
    			AcceptLanguage:   []language.Tag{language.Chinese, language.English},
    			DefaultLanguage:  language.Chinese,
    			FormatBundleFile: "toml",
    			UnmarshalFunc:    toml.Unmarshal,
    			Loader:           &ginI18n.EmbedLoader{fs},
    		}),
    	)
    }
    

    参考

    • https://pkg.go.dev/embed
    • https://github.com/gin-gonic/examples/blob/master/assets-in-binary/example02/main.go
    • https://gist.github.com/rsperl/6990289982130ea5be9b2e330f0a0229
    • https://github.com/gin-contrib/i18n/blob/master/embed.go
    • https://github.com/gin-contrib/i18n/blob/master/embed_test.go

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式