Go Bindata 内嵌静态资源
使用 Go 开发应用的时候,有时会遇到需要读取静态资源的情况。比如开发 Web 应用,程序需要加载模板文件生成输出的 HTML。在程序部署的时候,除了发布应用可执行文件外,还需要发布依赖的静态资源文件。这给发布过程添加了一些麻烦。既然发布单独一个可执行文件是非常简单的操作,就有人会想办法把静态资源文件打包进 Go 的程序文件中。下面就来看一些解决方案:
go-bindata
安装 go-bindata:
go get -u github.com/jteeuwen/go-bindata/...
注意: go get 地址最后的三个点 ...。这样会分析所有子目录并下载依赖编译子目录内容。go-bindata 的命令工具在子目录中。(还要记得把 $GOPATH/bin 加入系统 PATH)。
生成命令工具 go-bindata
go-bindata -o=app/asset/asset.go -pkg=asset source/... theme/... doc/source/... doc/theme/...
-o 输出文件到 app/asset/asset.go,
-pkg=asset 指定生成的包名 ,
然后是需要打包的目录,三个点...包括所有子目录。这样就可以把所有相关文件打包到 asset.go 且开头是 package asset 保持和目录一致。
使用静态文件的代码:
dirs := []string{"source", "theme", "doc"} // 设置需要释放的目录
for _, dir := range dirs {
// 解压dir目录到当前目录
if err := asset.RestoreAssets("./", dir); err != nil {
isSuccess = false
break
}
}
if !isSuccess {
for _, dir := range dirs {
os.RemoveAll(filepath.Join("./", dir))
}
}
asset.go 内的静态内容还是根据实际的目录位置索引。所以我们可以直接通过目录或者文件地址去操作。
-debug 开发模式
go-bindata 支持开发模式,即不嵌入静态内容,只生成操作方法到输出的 go 代码中,如:
go-bindata -debug -o=app/asset/asset.go -pkg=asset source/... theme/... doc/source/... doc/theme/...
-debug 参数开启开发模式。生成的代码会直接去读取静态文件到内存,而不是编码到代码中。代码文件更小,你更快速的编写业务逻辑。
// -pkg=asset, 打包的包名是 asset
bytes, err := asset.Asset("theme/default/post.html") // 根据地址获取对应内容
if err != nil {
fmt.Println(err)
return
}
t, err := template.New("tpl").Parse(string(bytes)) // 比如用于模板处理
fmt.Println(t, err)
http.FileSystem
http.FileSystem 是定义 HTTP 静态文件服务的接口。go-bindata 的第三方包 go-bindata-assetfs 实现了这个接口,支持 HTTP 访问静态文件目录的行为。以我们上面编译好的 asset.go 为例:
import (
"net/http"
"github.com/elazarl/go-bindata-assetfs"
"github.com/go-xiaohei/pugo/app/asset" // 用 pugo 的asset.go进行测试
)
func main() {
fs := assetfs.AssetFS{
Asset: asset.Asset,
AssetDir: asset.AssetDir,
AssetInfo: asset.AssetInfo,
}
http.Handle("/", http.FileServer(&fs))
http.ListenAndServe(":12345", nil)
}
访问 http://localhost:12345,就可以看到嵌入的 source,theme,doc 的目录列表页面,和 Nginx 查看静态文件目录一样的。
go generate
嵌入静态资源的工具推荐配合 go generate 使用。例如 pugo 的入口文件就有:
package main
import (
"os"
"time"
"github.com/go-xiaohei/pugo/app/command"
"github.com/go-xiaohei/pugo/app/vars"
"github.com/urfave/cli"
)
//go:generate go-bindata -o=app/asset/asset.go -pkg=asset source/... theme/... doc/source/... doc/theme/...
// ......
在编译的时候执行:
go generate && go build
这个是 go generate 的基本用法。更详细的了解可以看 官方博文。