gobuffalo/packr

GitHub: gobuffalo/packr

Packr 是一个将静态文件嵌入 Go 二进制文件的工具,让开发者无需额外携带资源文件即可分发单一可执行程序。

Stars: 3391 | Forks: 194

**注意:请考虑将您的项目迁移至 [embed](https://pkg.go.dev/embed),这是 Go 原生的文件嵌入功能, 或者 github.com/markbates/pkger。它具有惯用的 API、极少的依赖、更强大的测试套件(直接针对标准库的对应组件进行测试)、透明的工具等等。** https://blog.gobuffalo.io/introducing-pkger-static-file-embedding-in-go-1ce76dc79c65 # Packr (v2) [![GoDoc](https://godoc.org/github.com/gobuffalo/packr/v2?status.svg)](https://godoc.org/github.com/gobuffalo/packr/v2) [![Actions Status](https://static.pigsec.cn/wp-content/uploads/repos/cas/1e/1eb60c96331bf3b781460d138431e9ebaef63f0625894915fb88fc86344652c8.svg)](https://github.com/gobuffalo/packr/actions) Packr 是一个将静态资源打包进 Go 二进制文件的简单解决方案。最重要的是,它在开发过程中对开发者非常友好。 目前,支持的 go 版本包括: * 1.16.x * 1.17.x 尽管它可能(也可能不会)在旧版本上良好运行。 ## 介绍视频 要了解 Packr 的内容和初衷,请观看此简短视频:[https://vimeo.com/219863271](https://vimeo.com/219863271)。 ## 库安装 ### Go 1.16 及以上版本 ``` $ go install github.com/gobuffalo/packr/v2@v2.8.3 ``` 或 ``` $ go install github.com/gobuffalo/packr/v2@latest ``` ### Go 1.15 及以下版本 ``` $ go get -u github.com/gobuffalo/packr/... ``` ## 二进制文件安装 ### Go 1.16 及以上版本 ``` $ go install github.com/gobuffalo/packr/v2/packr2@v2.8.3 ``` 或 ``` $ go install github.com/gobuffalo/packr/v2/packr2@latest ``` ### Go 1.15 及以下版本 ``` $ go get -u github.com/gobuffalo/packr/packr2 ``` ## 新文件格式常见问题解答 在 `v2.0.0` 版本中,文件格式发生了变化,并且与 `packr-v1.x` 库不向后兼容。 #### `packr-v1.x` 可以读取新格式吗? 不,它不可以。由于新文件格式的工作方式,将其移植到 `packr-v1.x` 会比较困难。不过,欢迎提交 PR。 :) #### `packr-v2.x` 可以读取 `packr-v1.x` 文件吗? 是的,它可以,但这种能力最终会被淘汰。因此,我们建议您迁移到新格式。 #### `packr-v2.x` 可以生成 `packr-v1.x` 文件吗? 是的,它可以,但这种能力最终会被淘汰。因此,我们建议您迁移到新格式。 `--legacy` 命令适用于所有生成 `-packr.go` 文件的命令。 ``` $ packr2 --legacy ``` ## 用法 ### 在代码中 使用 Packr 的第一步是创建一个新的 box。一个 box 代表磁盘上的一个文件夹。一旦你有了一个 box,你就可以获取文件的 `string` 或 `[]byte` 表示形式。 ``` // set up a new box by giving it a name and an optional (relative) path to a folder on disk: box := packr.New("My Box", "./templates") // Get the string representation of a file, or an error if it doesn't exist: html, err := box.FindString("index.html") // Get the []byte representation of a file, or an error if it doesn't exist: html, err := box.Find("index.html") ``` ### 什么是 Box? Box 代表磁盘上的一个文件夹及其任何子文件夹,您希望在二进制文件中访问它们。使用 `packr2` CLI 编译二进制文件时,该文件夹的内容将被转换为可以编译到“标准” go 二进制文件中的 Go 文件。在编译后的二进制文件内部,这些文件将从内存中读取。在本地工作时,文件将直接从磁盘读取。这是一个无缝切换,不需要您进行任何特殊处理。 #### 示例 ``` ├── main.go └── templates ├── admin │   └── index.html └── index.html ``` 以下程序将读取 `./templates/admin/index.html` 文件并将其打印出来。 ``` package main import ( "fmt" "github.com/gobuffalo/packr/v2" ) func main() { box := packr.New("myBox", "./templates") s, err := box.FindString("admin/index.html") if err != nil { log.Fatal(err) } fmt.Println(s) } ``` ### 让开发变得简单 为了将静态文件放入 Go 二进制文件中,这些文件必须首先转换为 Go 代码。为此,Packr 提供了一些工具来帮助构建二进制文件。见下文。 然而,在开发过程中,必须不断运行工具来编译这些文件是非常痛苦的。 Packr 在查找文件时使用以下解析规则: 1. 在内存中(Go 二进制文件内部)查找文件 2. 在磁盘上(开发期间)查找文件 因为 Packr 知道如何回退到文件系统,所以开发者无需担心不断地将静态文件编译到二进制文件中。他们可以不受阻碍地进行工作。 Packr 进一步推进了文件解析。当声明一个新的 box 时,您使用一个相对路径,例如 `./templates`。当 Packr 收到此调用时,它会计算出该目录的绝对路径。通过这样做,这意味着可以保证 Packr 能够正确找到您的文件,即使您不是在创建 box 的目录中运行它。这有助于解决测试问题,在测试中 Go 会更改每个 package 的 `pwd`,使得相对路径难以处理。使用 Packr 时这不是问题。 ## 结合 HTTP 使用 box 实现了 [`http.FileSystem`](https://golang.org/pkg/net/http/#FileSystem) 接口,这意味着它可以用来提供静态文件。 ``` package main import ( "net/http" "github.com/gobuffalo/packr/v2" ) func main() { box := packr.New("someBoxName", "./templates") http.Handle("/", http.FileServer(box)) http.ListenAndServe(":3000", nil) } ``` ## 构建二进制文件 在构建 Go 二进制文件之前,请先运行 `packr2` 命令。它将查找代码中的所有 box,然后生成 `.go` 文件,将静态文件打包成可以捆绑到 Go 二进制文件中的字节。 ``` $ packr2 ``` 然后像平常一样运行您的 `go build command`。 *注意*:不建议将这些生成的 `-packr.go` 文件提交到版本库中。它们可能会很大,如果不小心的话很容易过时。建议您在运行 `packr2` 工具后始终运行 `packr2 clean`。 #### 清理 完成后,建议您运行 `packr2 clean` 命令。这将删除 Packr 为您创建的所有生成文件。 ``` $ packr2 clean ``` 为什么你要这样做?Packr 首先会查看存储在这些生成文件中的信息,如果信息不存在,它就会查看磁盘。这使得在开发中更容易使用。 ## 调试 `packr2` 命令会将所有参数传递给底层的 `go` 命令,这包括用于打印 `go build` 信息的 `-v` 标志。Packr 会寻找 `-v` 标志,并开启其自身的详细日志记录。这对于尝试了解 `packr` 命令在运行时正在做什么非常有用。 ## 常见问题解答 ### Go Templates 的编译错误 问:我有一个包含 Go 模板文件的程序,这些文件名为 `foo.go`,如下所示: ``` // Copyright {{.Year}} {{.Author}}. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package {{.Project}} ``` 当我运行 `packr2` 时,出现如下错误: ``` expected 'IDENT', found '{' ``` 答:Packr 的工作原理是在您的 `.go` 文件中搜索 [`github.com/gobuffalo/packr/v2#New`](https://godoc.org/github.com/gobuffalo/packr/v2#New) 或 [`github.com/gobuffalo/packr/v2#NewBox`](https://godoc.org/github.com/gobuffalo/packr/v2#NewBox) 调用。因为这些文件不是“正确”的 Go 文件,所以 Packr 无法解析它们以找到 box 声明。要解决此问题,您需要告诉 Packr 在搜索 box 时忽略这些文件。此问题的一些解决方案是: * 将文件重命名为其他名称。`.tmpl` 扩展名是命名此类文件的习惯用法。 * 将包含这些文件的文件夹重命名为以 `_` 开头,例如 `_templates`。Packr 和 Go 一样,在搜索 box 时会忽略以 `_` 字符开头的文件夹。 ### 动态 Box 路径 问:我需要使用变量来设置 box 的路径,但是 `packr.New("foo", myVar)` 无法正常工作。 答:Packr 在使用 [`github.com/gobuffalo/packr/v2#New`](https://godoc.org/github.com/gobuffalo/packr/v2#New) 时会尝试“自动”设置其解析目录,但是,对于动态路径,您需要手动设置它: ``` box := packr.New("foo", "|") box.ResolutionDir = myVar ``` ### 我不想打包文件,但仍想使用 Packr 接口。 问:我想编写使用 Packr 工具的代码,但实际上并不将文件打包到我的二进制文件中。我该怎么做? 答:使用 [`github.com/gobuffalo/packr/v2#Folder`](https://godoc.org/github.com/gobuffalo/packr/v2#Folder) 会返回一个可以像平常一样使用的 `*packr.Box`,但在编译时会被 Packr 工具排除。 ### Packr 未找到任何 Box 问:我运行了 `packr2 -v` 但它没有找到我的 box: ``` DEBU[2019-03-18T18:48:52+01:00] *parser.Parser#NewFromRoots found prospects=0 DEBU[2019-03-18T18:48:52+01:00] found 0 boxes ``` 答:Packr 的工作原理是解析 `.go` 文件以查找 [`github.com/gobuffalo/packr/v2#Box`](https://godoc.org/github.com/gobuffalo/packr/v2#Box) 和 [`github.com/gobuffalo/packr/v2#NewBox`](https://godoc.org/github.com/gobuffalo/packr/v2#NewBox) 声明。如果运行 `packr2` 的文件夹中没有任何 `.go` 文件,它就无法找到这些声明。要解决此问题,请在包含您 `.go` 文件的目录中运行 `packr2` 命令。 ### Box 接口 问:我希望能通过传入模拟的 box 来轻松测试我的应用程序。我该怎么做? 答:Packr 的 box 和文件符合 [`github.com/gobuffalo/packd`](https://godoc.org/github.com/gobuffalo/packd) 中定义的接口。更改您的应用程序以使用这些接口,而不是具体的 Packr 类型。 ``` // using concrete type func myFunc(box *packr.Box) {} // using interfaces func myFunc(box packd.Box) {} ```
标签:EVTX分析, Go, Ruby工具, SOC Prime, 工具库, 开发工具, 文档结构分析, 日志审计, 编译嵌入, 静态资源打包