对于 Go 语言开发者来说,在享受语言便利性的同时,最终编译的单一可执行文件也是我们所热衷的。

但是,Go在编译成二进制文件时并没有把我们的静态资源文件编译进去,如果我们开发的是web应用的话就需要想办法把我们的静态文件也编译进去。

本文收集了一些Go语言中用来在编译过程中将静态文件打包到编译文件的方法。

go-bindata

在 Go 语言的 Awesome

中你可以看到很多静态打包库,但是,你却看不到 go-bindata, go-bindata

明显更受欢迎,更流行。

go-bindata 很简单,设计理念也不难理解。它的任务就是讲静态文件封装在一个 Go 语言的 Source Code 里面,然后提供一个统一的接口,你通过这个接口传入文件路径,它将给你返回对应路径的文件数据。这也就是说它不在乎你的文件是字符型的文件还是字节型的,你自己处理,它只管包装。

简单来说就是它可以把我们的静态文件生成 .go

文件,这样就可以编译成二进制文件,项目启动的时候再把这个 .go

文件再释放成静态文件

使用

打包整个静态目录,使用的时候释放

# 目录结构

ConfigTest

├── asset

│ └── asset.go 静态文件编译之后的go文件

├── config # 静态文件目录

│ ├── rule.yaml

│ └── rule.json

├── cli # 运行目录

│ ├── config 执行main释放出来的静态文件

│ │ ├── rule.yaml

│ │ └── rule.json

│ └── main # main.go编译之后生成的二进制执行文件

└── main 程序目录

└── main.go # 源码

执行命令将静态文件打包成go文件

go-bindata -o=./asset/asset.go -pkg=asset config/...

-o # 指定打包后生成的go文件路径

-pkg # 指定go文件的包名

config/... # 指定需要打包的静态文件路径

main函数中解压静态文件

package main

import "ConfigTest/asset"

func main() {

dirs := []string{"config"} // 设置需要释放的目录

for _, dir := range dirs {

// 解压dir目录到当前目录

if err := asset.RestoreAssets("./", dir); err != nil {

break

}

}

}

编译 main.go

执行二进制文件

cd cli && go build ../main/main.go

./main

# 执行之后会自动解压出config目录以及下面的静态文件

使用

目录结构

ConfigTest

├── asset

│ └── asset.go 静态文件编译之后的go文件

├── cli # 运行目录

│ ├── config

│ │ ├── config.json

│ │ └── config.yaml

│ └── main # main.go编译之后生成的二进制执行文件

├── config # 配置文件目录

│ ├── config.json

│ └── config.yaml

└── main # 程序目录

└── main.go # 源码

yaml配置文件内容

enabled: true

path: aaaaa

id: 10

json文件内容

{

"enabled": true,

"path": "xxxx",

"id": 111

}

main.go

package main

import (

"ConfigTest/asset"

"encoding/json"

"fmt"

"log"

"os"

"path/filepath"

yaml "gopkg.in/yaml.v2"

)

type conf struct {

Enabled bool

Path string

ID int

}

func (c *conf) ReadYaml() {

data, _ := asset.Asset("config/config.yaml")

err := yaml.Unmarshal(data, &c)

if err != nil {

log.Fatalf("Unmarshal: %v", err)

}

}

func (c *conf) ReadJson() {

data, _ := asset.Asset("config/config.json")

err := json.Unmarshal(data, &c)

if err != nil {

log.Fatalf("Unmarshal: %v", err)

}

}

func restore() {

dirs := []string{"config"} // 设置需要释放的目录

isSuccess := true

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))

}

}

}

func main() {

var c, j conf

j.ReadJson()

fmt.Println("json:", j)

c.ReadYaml()

fmt.Println("yaml:", c)

fmt.Println("释放静态文件")

restore()

}

执行命令将静态文件打包成go文件

go-bindata -o=./asset/asset.go -pkg=asset config/...

-o # 指定打包后生成的go文件路径

-pkg # 指定go文件的包名

config/... # 指定需要打包的静态文件路径

编译 main.go

执行二进制文件

cd cli && go build ../main/main.go

./main

json: {true xxxx 111}

yaml: {true aaaaa 10}

释放静态文件

# 执行之后会自动解压出config目录以及下面的静态文件

http.FileSystem

http.FileSystem

是定义 HTTP 静态文件服务的接口。 go-bindata

的第三方包 go-bindata-assetfs

实现了这个接口,支持 HTTP 访问静态文件目录的行为。

// import (

// "net/http"

// "github.com/elazarl/go-bindata-assetfs"

// "github.com/go-xiaohei/pugo/app/asset" // 用 pugo 的asset.go进行测试

// )

func myhttp() {

fs := assetfs.AssetFS{

Asset: asset.Asset,

AssetDir: asset.AssetDir,

AssetInfo: asset.AssetInfo,

}

http.Handle("/", http.FileServer(&fs))

http.ListenAndServe(":12345", nil)

}

func main() {

myhttp()

}

访问 http://localhost:12345

,就可以看到嵌入的静态资源目录的内容了

go.rice

go.rice

也支持打包静态文件到 go 文件中,但是行为和 go-bindata

很不相同。从使用角度, go.rice

其实是更便捷的静态文件操作库。打包静态文件反而是顺带的功能。

安装

go get github.com/GeertJohan/go.rice/...

使用

go.rice

把一个目录认为是一个 rice.Box

操作

import (

"fmt"

"html/template"

"github.com/GeertJohan/go.rice"

)

func main() {

// 这里写相对于的执行文件的地址

box, err := rice.FindBox("theme/default")

if err != nil {

println(err.Error())

return

}

// 从目录 Box 读取文件

str, err := box.String("post.html")

if err != nil {

println(err.Error())

return

}

t, err := template.New("tpl").Parse(str)

fmt.Println(t, err)

}

命令

go.rice 的打包命令是 rice。用起来非常直接:在有使用 go.rice 操作的 go 代码目录,直接执行 rice embed-go:

rice embed-go

rice -i "github.com/fuxiaohei/xyz" embed-go // -i 处理指定包里的 go.rice 操作

他就会生成当前包名下的、嵌入了文件的代码 rice-box.go

。但是,它不递归处理 import。他会分析当前目录下的 go 代码中 go.rice

的使用,找到对应需要嵌入的文件夹。但是子目录下的和 import 的里面的 go.rice

使用不会分析,需要你手动 cd

过去或者 -i

指定要处理的包执行命令。这点来说非常的不友好。

http.FileSystem

go.rice

是直接支持 http.FileSystem

接口:

func main() {

// MustFindBox 出错直接 panic

http.Handle("/", http.FileServer(rice.MustFindBox("theme").HTTPBox()))

http.ListenAndServe(":12345", nil)

}

有点略繁琐的是 rice.FindBox(dir)

只能加载一个目录。因此需要多个目录的场景,会有代码:

func main() {

http.Handle("/img", http.FileServer(rice.MustFindBox("static/img").HTTPBox()))

http.Handle("/css", http.FileServer(rice.MustFindBox("static/css").HTTPBox()))

http.Handle("/js", http.FileServer(rice.MustFindBox("static/js").HTTPBox()))

http.ListenAndServe(":12345", nil)

}

esc

esc 的作者在研究几款嵌入静态资源的 工具 后,发觉都不好用,就自己写出了 esc。它的需求很简单,就是嵌入静态资源 和 支持 http.FileSystem

。esc 工具也这两个主要功能。

安装

go get github.com/mjibson/esc

使用

使用方法和 go-bindata 类似:

// 注意 esc 不支持 source/... 三个点表示所有子目录

go-bindata -o=asset/asset.go -pkg=asset source theme doc/source doc/theme

http.FileSystem

import (

"net/http"

"asset" // esc 生成 asset/asset.go

)

func main() {

fmt.Println(asset.FSString(false, "/theme/default/post.html")) // 读取单个文件

http.ListenAndServe(":12345", http.FileServer(asset.FS(false))) // 支持 http.FileSystem,但是没有做展示目录的支持

}

esc 有个较大的问题是只能一个一个文件操作,不能文件夹操作,没有类似 go-bindata

的 asset.RestoreDir()

方法。并且没有方法可以列出嵌入的文件的列表,导致也无法一个一个文件操作,除非自己写死。这是我不使用他的最大原因。

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语言打包html,Go语言-打包静态文件相关推荐

  1. 【客服系统】在线客服系统源码外贸聊天通讯带翻译多语言支持网页安卓苹果打包封装APP

    随着全球化的加速推进,外贸行业对于在线客服系统的需求日益增长.一款功能强大.支持多语言交流.适用于网页和移动端的在线客服系统源码成为了众多企业的首选.本文将介绍一款名为"外贸聊天通讯带翻译多 ...

  2. c语言 udp 解包_UDP打包及解包问题

    UDP打包及解包问题 (2012-04-11 00:12:39) 标签: 打包 包 杂谈 UDP打包及解包问题第一个问题: 想问下在VC++开发平台下,是否提供了UDP协议打包和解包的接口函数?通常所 ...

  3. GO语言 go build -ldflags Windows 打包精简方式

    打包windows上运行的exe文件: go build -ldflags -H=windowsgui -o xx.exe main.go 去掉debug调试信息,缩小打包后文件: go build ...

  4. C语言学习笔记--动态库和静态库的使用

    link 1.C语言中的链接器 (1)每个 C 语言源文件被编译后生成目标文件,这些目标文件最终要被链接在一起生成可执行文件. (2)链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块 ...

  5. 编译型与解释型、动态语言与静态语言、强类型语言与弱类型语言概念辨析

    编译型与解释型.动态语言与静态语言.强类型语言与弱类型语言概念辨析 转自:https://blog.csdn.net/u010533843/article/details/76215487 编译型和解 ...

  6. Django模板、配置文件、静态文件及案例实现(创建模板、设置模板查找路径、模板接收视图传入的数据、模板处理数据、BASE_DIR、DEBUG、本地语言与时区、App应用配置)

    1.Django模板 网站如何向客户端返回一个漂亮的页面呢? 漂亮的页面需要html.css.js. 可以把这一堆字段串全都写到视图中, 作为HttpResponse()的参数,响应给客户端. 存在的 ...

  7. pyinstaller深入使用,打包指定模块,打包静态文件

    1.标准用法: pyinstall  **.py  直接打包     pyinstall -F **.py  打包成单文件     pyinstall -W **.py  去掉控制台窗口,黑窗口    ...

  8. iOS架构-静态库.framework手动打包及脚本化打包(5)

    引用一张博客的图片来理解下基本知识(http://www.cnblogs.com/oc-bowen/p/7478461.html) 我们可以看出.a的封装和.framework的封装差不多,也有模拟器 ...

  9. vue 打包html静态页面,vue项目打包、vue项目打包后空白界面解决办法

    Vue脚手架提供了一个命令npm run build进行打包项目,在package.json中有一个build属性,对应执行命令node build/build.js.执行成功后,项目目录下多了一个d ...

最新文章

  1. 信阳学院大一计算机考试题库,韩山师范学院大一计算机考试题库网页制作的试题...
  2. JavaScript语言基础2
  3. Codeforces 41D Pawn 简单dp
  4. java编程里的values怎么使用,详解Java编程中super关键字的用法
  5. Java设计模式-适配器模式Adapter
  6. LeetCode 66 加一
  7. Spring Boot中对log4j进行多环境不同日志级别的控制
  8. Oralce 日期操作
  9. Centos/Linux在线环境下载安装包,到离线环境安装,并解决依赖问题
  10. 集成测试:固定装置多于自动装置
  11. 很WEB很2.0---ThunderBird
  12. rfid破解 BLE Hacking
  13. 儿童python编程教程-一款儿童编程入门的理想工具——PythonTurtle
  14. 对ashx请求用Gzip,Deflated压缩
  15. 第二人生的源码分析(十四)人物角色的实现
  16. red5+obs+ffmpeg 推流实现单方直播 window +linux
  17. 多视图信息瓶颈表征学习
  18. 移动开发技术第四次大作业
  19. java B2B2C源码电子商务平台 ---搭建Eureka注册中心
  20. 生活实用之清洗小龙虾

热门文章

  1. 用scikit-learn进行LDA降维
  2. 在VS2012中实现ExtJS的智能提示
  3. springboot发送邮件_SpringBoot发送邮件如何实现,SpringBoot发送邮件详解(附代码)...
  4. python点击网页按钮 没有id_button没有id,没有onclick事件。点击却有提交的功能,如何实现的?...
  5. tensorflow版本及其对应环境
  6. 行为识别(HAR)调研
  7. Metapath2vec:Scalable Representation Learning for Heterogeneous Networks(结构化深度网络特征表示)
  8. OpenCV--矩阵操作总结
  9. 计算机视觉:相机成像原理:世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换(转载)
  10. leetcode50:Pow(x, n)详解——pygo