系列文章目录
第一章 Go 语言打包动态文件以及如何与 Gin 一起应用 Go-bindata
[TOC]
前言
前几天,开始学习用 Go 语言开发一个外部我的项目来帮忙解决测试环境中的一些不便当的问题。因为开发的小我的项目中存在一些动态文件和配置文件,第一打包的时候发现并没有将动态文件打包进入可执行文件,这样在公布的时候又须要手动拷贝一下动态文件,这样就很麻烦了。在一些网上材料上发现了 go-bindata
。这样我还是只散发一个文件就能够了,不过打包进去的文件会大一点。
一、go-bindata 是什么?
his package converts any file into managable Go source code. Useful for embedding binary data into a go program. The file data is optionally gzip compressed before being converted to a raw byte slice.
It comes with a command line tool in the go-bindata sub directory. This tool offers a set of command line options, used to customize the output being generated.
go-bindata 将任何文件封装在一个 Go 语言的 Source Code 外面,文件数据在转换为原始字节时能够抉择应用 gzip 压缩,同时提供了对立的接口,帮忙获取原始的文件数据
二、应用步骤
1. 装置
go get -u github.com/jteeuwen/go-bindata/...
2. 应用
应用 go-bindata --help
能够查看具体的应用形式
go-bindata --help
Usage: go-bindata [options] <input directories>
-debug
Do not embed the assets, but provide the embedding API. Contents will still be loaded from disk.
-dev
Similar to debug, but does not emit absolute paths. Expects a rootDir variable to already exist in the generated code's package.
-fs
Whether generate instance http.FileSystem interface code.
-ignore value
Regex pattern to ignore
-mode uint
Optional file mode override for all files.
-modtime int
Optional modification unix timestamp override for all files.
-nocompress
Assets will *not* be GZIP compressed when this flag is specified.
-nomemcopy
Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.
-nometadata
Assets will not preserve size, mode, and modtime info.
-o string
Optional name of the output file to be generated. (default "./bindata.go")
-pkg string
Package name to use in the generated code. (default "main")
-prefix string
Optional path prefix to strip off asset names.
-tags string
Optional set of build tags to include.
-version
Displays version information.
这里我的项目的大略构造如下
├── conf
│ └── app.ini
├── main.go
├── routers
│ └── router.go
├── setting
│ └── setting.go
└── template
├── css
│ └── chunk-vendors.c6d02872.css
├── favicon.ico
├── fonts
│ └── element-icons.535877f5.woff
├── img
│ └── Avatar.41ba4b7a.jpg
├── index.html
└── js
├── app.40872d4f.js
为了查看不便和限于篇幅,删除了一些无关的文件
在打包的时候想将 /conf
和 /template
,打包进生成的文件中
最根本的应用形式是 go-bindata <input directories>
这里咱们参数全副应用默认的,这样将创立 bindata.go
且生成的文件放在根目录的 main 包下
go-bindata template/... conf/...
如果要批改最终生成文件名和包名能够应用 -o
和 -pkg
参数,这样就在 asset 下生成 asset.go 文件且包为 asset
go-bindata -o=asset/asset.go -pkg=asset template/... conf/...
3. 读取文件
通过上述形式生成的 asset.go 文件中蕴含 3 个获取文件信息的办法
- func Asset(name string) ([]byte, error) 依据文件名加载文件返回 byte
- func AssetNames() []string 返回所有的文件列表
- func AssetInfo(name string) (os.FileInfo, error) 返回文件信息
如果你查看源文件,能够查看 _bindata
中保护了文件的信息
var _bindata = map[string]func() (*asset, error){
"template/css/app.ee8ee5dd.css": templateCssAppEe8ee5ddCss,
"template/favicon.ico": templateFaviconIco,
"template/fonts/element-icons.535877f5.woff": templateFontsElementIcons535877f5Woff,
"template/img/Avatar.41ba4b7a.jpg": templateImgAvatar41ba4b7aJpg,
"template/index.html": templateIndexHtml,
"template/js/app.40872d4f.js": templateJsApp40872d4fJs,
"conf/app.ini": confAppIni,
}
如果咱们想读取 conf/app.ini 的文件,能够用应用
conf_ini, _ := asset.Asset("conf/app.ini")
这样简略的操作就实现了
三、和 Gin 一起应用
在失常应用 Gin 时,咱们个别这样配置动态资源的应用
r := gin.Default()
r.LoadHTMLGlob("template/index.html")
r.Static("/css", "./template/css")
r.Static("/fonts", "./template/fonts")
r.Static("/img", "./template/img")
r.Static("/js", "./template/js")
r.StaticFile("/favicon.ico", "./template/favicon.ico")
// 首页
r.GET("/", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)
})
为了将应用打包好的动态资源,咱们须要换种形式进行打包和配置
1. 应用 go-bindata-assetfs 进行打包
Serve embedded files from go-bindata
with net/http.
go-bindata-assetfs 实现了 http.FileSystem 帮忙咱们更好的在 http 服务上应用生成的文件
2. 装置 go-bindata-assetfs
这个须要和 go-bindata
一起装置,如果曾经装置了 go-bindata
则不须要再次装置
go get github.com/go-bindata/go-bindata/...
go get github.com/elazarl/go-bindata-assetfs/...
3. 打包文件
这里咱们只需将 go-bindata
换成 go-bindata-assetfs
即可,两者的应用形式雷同
go-bindata-assetfs -o=asset/asset.go -pkg=asset template/... conf/...
4. 重新配置
r := gin.Default()
fs := assetfs.AssetFS{Asset: asset.Asset, AssetDir: asset.AssetDir, AssetInfo: asset.AssetInfo, Prefix: "template", Fallback: "index.html"}
r.StaticFS("/css", &fs)
r.StaticFS("/fonts", &fs)
r.StaticFS("/img", &fs)
r.StaticFS("/js", &fs)
r.StaticFS("/favicon.ico", &fs)
r.StaticFS("/index", &fs)
r.GET("/", func(c *gin.Context) {c.Writer.WriteHeader(200)
indexHtml, _ := asset.Asset("template/index.html")
_, _ = c.Writer.Write(indexHtml)
c.Writer.Header().Add("Accept", "text/html")
c.Writer.Flush()})
对于
fs := assetfs.AssetFS{Asset: asset.Asset, AssetDir: asset.AssetDir, AssetInfo: asset.AssetInfo, Prefix: "template", Fallback: "index.html"}
其中:
Prefix: "template"
是为了在查问文件时去除 template
前缀,例如原文件门路为 "template/css/app.ee8ee5dd.css"
=> /css/app.ee8ee5dd.css
不便和前端申请对应
Fallback: "index.html"
意思为如何查问不到则默认返回 index.html
文件,因为配置了前缀,这里返回的应该是 template/index.html
5. 日常开发
在日常开发中,没有必要没改变一下动态文件就要从新生成 asset.go,此时咱们能够应用 -debug
模式生成 asset.go 文件,这样拜访文件还是应用的实在文件
go-bindata-assetfs -debug -o=asset/asset.go -pkg=asset template/... conf/...
总结
通过 go-bindata
和 go-bindata-assetfs
的应用,咱们能够将动态文件进行打包,最终提供单个散发文件,简化部署和应用。
题外
提一下 go-bindata 我的项目之前的一些周折。
如果你搜寻 go-bindata 的文章,会发现晚期的文章指向的我的项目地址往往是:https://github.com/jteeuwen/g…。那是最早的我的项目地址,jteeuwen 是原作者 Jim Teeuwen 的账号。
但不晓得什么时候,因为什么起因,原作者把我的项目敞开了,连 jteeuwen 这个账号都删除了。(从现存线索推断,大概是 2018 年的事)
当初原地址也有一个我的项目,但曾经 不是原我的项目,也 不再保护 了。那是有人发现 go-bindata 删除后,为了让依赖它的我的项目不会报错,从新注册了 jteeuwen 这个账号,从新 fork 了这个我的项目 (真正原我的项目已删,是从一个 fork 那里 fork 的)。因为初衷是让某个我的项目可能持续工作(据说是曾经没法批改的私人我的项目,所以也不能指向新的地址),并没有打算持续保护,也不想假冒原我的项目,所以这个我的项目设为了 archived (read only)。详情能够参考以下探讨:
https://github.com/jteeuwen/g…
https://github.com/jteeuwen/d…
当初给出的我的项目地址,不确定跟原作者有没有关系——预计是没有的。那它不过是泛滥 fork 的其中一个。选它仅仅因为它最沉闷、关注人数最多。这可能跟它挂在了同名 organization 下有肯定关系,也可能外面有某个大牛。
理由并不重要,只须要晓得它最沉闷是一个共识,就够了。
题外这段援用 https://jaycechant.info/2020/…
参考
- https://github.com/jteeuwen/g…
- https://github.com/elazarl/go…
- https://github.com/go-bindata…