马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
背景
想把本身的一个SpringBoot应用打包成可实验文件。看看Golang是如何做到的。
Go 的 go:embed 功能介绍与打包 JAR 文件示例
go:embed 是 Go 1.16 引入的一个强大功能,它允许在编译时将外部文件或目录嵌入到 Go 程序中。下面介绍如何利用 go:embed 来嵌入 JAR 文件。
1. go:embed 底子介绍
基本特性
- 编译时嵌入文件内容
- 支持嵌入单个文件、多个文件或整个目录
- 支持三种嵌入类型:
- string - 用于文本文件
- []byte - 用于二进制文件
- embed.FS - 用于文件系统(支持多个文件/目录)
基本语法
- import "embed"
- //go:embed filename.txt
- var fileContent string
- //go:embed image.png
- var imageData []byte
- //go:embed templates/*
- var templatesFS embed.FS
复制代码 2. 嵌入 JAR 文件示例
假设你有一个需要嵌入的 app.jar 文件,以下是完整示例:
项目结构
- project/
- ├── embedded/
- │ └── app.jar # 要嵌入的JAR文件
- ├── main.go
- └── go.mod
复制代码 代码实现
- package main
- import (
- "embed"
- "io"
- "log"
- "os"
- "path/filepath"
- )
- //go:embed embedded/app.jar
- var jarFile []byte
- func main() {
- // 指定输出路径(可以是临时目录或特定位置)
- outputPath := filepath.Join(os.TempDir(), "app.jar")
-
- // 将嵌入的JAR写入文件系统
- err := os.WriteFile(outputPath, jarFile, 0755)
- if err != nil {
- log.Fatalf("Failed to write JAR file: %v", err)
- }
-
- log.Printf("JAR file extracted to: %s", outputPath)
-
- // 现在你可以使用这个JAR文件,比如通过exec.Command运行它
- // exec.Command("java", "-jar", outputPath)
- }
复制代码 3. 高级用法:嵌入多个文件或目录
假如你有多个 JAR 文件需要嵌入:
- //go:embed embedded/*.jar
- var jarFiles embed.FS
- func main() {
- // 列出所有嵌入的JAR文件
- entries, err := jarFiles.ReadDir("embedded")
- if err != nil {
- log.Fatal(err)
- }
-
- // 提取所有JAR文件
- for _, entry := range entries {
- if filepath.Ext(entry.Name()) == ".jar" {
- data, err := jarFiles.ReadFile("embedded/" + entry.Name())
- if err != nil {
- log.Printf("Failed to read %s: %v", entry.Name(), err)
- continue
- }
-
- outputPath := filepath.Join(os.TempDir(), entry.Name())
- err = os.WriteFile(outputPath, data, 0755)
- if err != nil {
- log.Printf("Failed to write %s: %v", entry.Name(), err)
- continue
- }
-
- log.Printf("Extracted %s to %s", entry.Name(), outputPath)
- }
- }
- }
复制代码 4. 利用注意事项
- 路径规则:
- go:embed 路径是相对于包罗该指令的Go源文件的
- 不能包罗 . 或 .. 等路径组件
- 不能匹配到父目录中的文件
- 文件巨细限制:
- Go 1.16+ 对嵌入文件巨细没有硬性限制
- 但非常大的文件可能会增加编译时间和二进制巨细
- 构建约束:
- 嵌入的文件必须在构建时可用
- 假如文件不存在,构建会失败
- 安全考虑:
- 提取嵌入文件时要注意目标路径的权限
- 考虑利用暂时目录并在程序退出时清算
5. 现实应用场景
- 打包Java应用:将依靠的JAR文件嵌入Go程序,然后通过exec.Command调用Java运行
- 嵌入式数据库:如SQLite数据库文件
- Web服务器资源:HTML/CSS/JS等前端资源
- 配置文件:默认配置模板
6. 完整示例:运行嵌入的JAR
- package main
- import (
- "embed"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- )
- //go:embed app.jar
- var jarFile []byte
- func main() {
- // 创建临时文件
- tmpFile, err := os.CreateTemp("", "embedded-*.jar")
- if err != nil {
- log.Fatal(err)
- }
- defer os.Remove(tmpFile.Name()) // 程序退出时删除
-
- // 写入JAR内容
- if _, err := tmpFile.Write(jarFile); err != nil {
- log.Fatal(err)
- }
- if err := tmpFile.Close(); err != nil {
- log.Fatal(err)
- }
-
- // 执行Java命令
- cmd := exec.Command("java", "-jar", tmpFile.Name())
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
-
- log.Println("Starting Java application...")
- if err := cmd.Run(); err != nil {
- log.Fatalf("Java application failed: %v", err)
- }
- }
复制代码 通过这种方式,你可以将Java应用程序打包到Go二进制文件中,然后通过Go程序来分发和启动它。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |