paint-brush
如何将静态资源嵌入到 Go 项目中经过@kibizovd
837 讀數
837 讀數

如何将静态资源嵌入到 Go 项目中

经过 David Kibizov3m2023/11/28
Read on Terminal Reader

太長; 讀書

使用独立应用程序可以简化部署和分发,因为它只是一个可执行的二进制文件。 Rice、Statik 和 Bindata 都可用于将资源嵌入到 Go 应用程序中。让我们创建一个index.html模板并使用静态资源来测试它来测试Go代码。
featured image - 如何将静态资源嵌入到 Go 项目中
David Kibizov HackerNoon profile picture

我想在 Go 中创建一个小型独立 Web 应用程序,这与常规 Web 应用程序相反,在常规 Web 应用程序中,资源将通过 CDN 或 HTTP 服务器(例如 Nginx)单独提供。


但是,如果性能不是关键问题或者应用程序旨在用于低流量,则使用独立应用程序可以简化部署和分发,因为它只是一个可执行二进制文件。


有几个包可用于将资源嵌入到 Go 应用程序中:



我不会深入研究每个库的具体细节,但我更喜欢bindata方法,因为它易于使用且得到积极支持。

入门

首先,让我们在项目的frontend/目录中创建一个index.html

 <html> <body> Hello, World! </body> </html>


现在我们已经有了一个项目设置和一个要测试的静态资源,让我们使用以下命令安装bindata

 go get -u github.com/jteeuwen/go-bindata/...


我们已准备好运行 Web 应用程序的后端代码。创建main.go文件,并复制以下代码:

 package main import ( "bytes" "io" "net/http" ) //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/... func static_handler(rw http.ResponseWriter, req *http.Request) { var path string = req.URL.Path if path == "" { path = "index.html" } if bs, err := Asset(path); err != nil { rw.WriteHeader(http.StatusNotFound) } else { var reader = bytes.NewBuffer(bs) io.Copy(rw, reader) } } func main() { http.Handle("/", http.StripPrefix("/", http.HandlerFunc(static_handler))) http.ListenAndServe(":3000", nil) }


此代码中的重要行:

 //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...


上面的行允许我们在调用go generate时运行go-bindata命令。从版本 1.4 开始,您可以在生成阶段运行自定义命令。只需将//go:generate command argument...添加到您的 go 文件即可。


go-bindata命令行有多个参数,因此请查看文档以了解如何使用它。在我们的例子中,我们说:


  • -prefix "frontend/"定义静态路径名的一部分


  • -pkg main定义生成代码中使用的包名称


  • -o bindata.go定义生成文件的名称


运行go generate命令后,您应该会看到一个名为bindata.go的生成文件。您的项目的结构应该如下所示:

 . │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go


提供静态文件的逻辑在static_handler函数中,该函数接收请求并检查路径是否与静态路径匹配。检查是使用Asset函数完成的,由bindata.go用户自动导出。如果资源不存在,我们返回404 ,否则,我们返回资源的内容。


其余代码用于创建 Web 应用程序并绑定我们的static_handler模板以匹配/的所有传入请求。如果您无法理解此代码,请查看http package的 Go 官方文档


快速提醒一下 Go 如何处理包,如果标识符名称的第一个字母以大写字母开头,则所有标识符将自动导出到具有相同名称的其他包。


基于这个规则, bindata.go文件main包提供了Asset功能。这会加载并返回给定名称的资源。如果找不到或无法加载资源,它将返回错误。