Go - 打包静态文件-bin文件直接使用

Go - 打包静态文件-bin文件直接使用

一、前言

使用 Go 开发应用的时候,有时会遇到需要读取静态资源的情况。

  • 比如:开发 Web 应用,程序需要加载模板文件生成输出的 HTML。在程序部署的时候,除了发布应用可执行文件外,还需要发布依赖的静态资源文件。这给发布过程添加了一些麻烦。

  • 比如:项目中有一些静态模板需要渲染,然而这些模板又是固定的静态文件

如果不打包处理这种静态文件:发布单独挂载这种静态文件相对比较麻烦,就有人会想办法把静态资源文件打包进 Go 的程序文件中。

下面介绍两种打包方式:go-bindata、go:embed


二、go-bindata打包静态资源

go-bindata 将任何文件封装在一个 Go 语言的 Source Code 里面,文件数据在转换为原始字节时可以选择使用 gzip 压缩,同时提供了统一的接口,帮助获取原始的文件数据

2.1 安装

go 复制代码
go get -u github.com/go-bindata/go-bindata/...

安装打包工具 go-bindata 到GOPATH/bin中,输入下面的命令检查下是否安装成功:

go 复制代码
go-bindata  --version

2.2 打包

go 复制代码
go-bindata -o=resource.go -pkg=resource   ./resource/...
  • 将把./resource目录下的所有文件转换为Go代码,注意后面的... 代表讲该文件下面所有的文件及子文件打包
  • 生成一个名为resource.go的文件,你可以在你的Go代码中通过main包来访问这些静态文件。

如果你查看源文件,可以查看 _bindata 中维护了文件的信息


2.3 使用

  • Asset(name string) ([]byte, error) :根据资源名称返回文件内容
  • MustAsset(name string) []byte :根据资源名称返回文件内容
  • AssetInfo(name string) (os.FileInfo, error) : 根据资源名称返回文件信息
  • AssetNames() []string :返回所有的资源名称
  • AssetDir(name string) ([]string, error) : 返回某一个文件夹一层的名称
  • RestoreAsset(dir, name string) error
  • RestoreAssets(dir, name string) error

三、go:embed 打包静态资源

Go 1.16版本开始,可以使用go:embed来嵌入文件。

embed是在Go 1.16中新加包。它通过//go:embed指令,可以在编译阶段将静态资源文件打包进编译好的程序(exe)中,并提供访问这些文件的能力。

  • 对于单个的文件,支持嵌入类型为stringbyte slice
  • 对于多个文件和文件夹,支持嵌入为新的文件系统FS
  • 比如导入"embed"包,即使无显式的使用
  • go:embed指令用来嵌入,必须紧跟着嵌入后的变量名

注意:go embed的使用只能用于包级别声明的变量(全局变量)


3.1 embed 要嵌入的文件

go 复制代码
//go:embed 要嵌入的文件
  • 示例一
go 复制代码
import (
    _ "embed"
    "fmt"
)
​
//go:embed repos.tmpl
var data string
​
func main() {
    fmt.Println(data)
}
  • 示例二
go 复制代码
import (
    _ "embed"
    "fmt"
)
​
//go:embed repos.tmpl
var data []byte
​
func main() {
    fmt.Println(string(data))
}

3.2 嵌入文件系统FS

对于多个文件和文件夹,支持嵌入为新的文件系统FS

embed.FS提供了三个方法进行访问:

vbnet 复制代码
Open(name string) (fs.File, error)   根据资源key返回文件
​
ReadFile(name string) ([]byte, error)  根据资源key返回文件内容
​
ReadDir(name string) ([]fs.DirEntry, error)  根据key读取文件夹   
  • 嵌入文件夹

使用embed.FS嵌入的文件变量,具有3种功能,如下所示:

go 复制代码
import (
    "embed"
    _ "embed"
    "fmt"
)
​
//go:embed resource
var data embed.FS
​
func main() {
    // 直接读取文件
    file, err := data.ReadFile("resource/cmd/main.go.tmpl")
    fmt.Println(string(file), err)
}
  • 嵌入多个文件
go 复制代码
import (
    "embed"
    _ "embed"
    "fmt"
)
​
//go:embed aa.text bb.text
var data embed.FS
​
func main() {
    file, err := data.ReadFile("aa.text")
    fmt.Println(string(file), err)
}

四、链接

相关推荐
梦想很大很大11 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰16 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘20 小时前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤20 小时前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt111 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉7 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想