欲买桂花同载酒,荒泷天下第一斗。|

janbar

园龄:4年6个月 粉丝:29 关注:10

2021-02-18 17:40 阅读 1449 评论 0 推荐

golang官方嵌入文件到可执行程序

前言

在go官方出嵌入文件的方法前我在网上找过,并且自己还研究过,虽然没有问题,但是既然官方支持还是用起来吧。
看了下go源码embed/embed.go很简单,并且看embed/internal/embedtest/embed_test.go就知道如何使用。

示例程序

嵌入文件直接访问

原理是使用go:embed标签来完成。下面是直接读取文件内容,需要注意下面几点。
文件不是utf8编码时,输出内容为中文会乱码。
测试过嵌入文件只能为源码文件同级目录和子目录下的文件,试过其他目录的绝对路径或相对路径会报错。
如果路径包含空格可以使用双引号或反引号括起来。
变量的类型只能是string、[]byte、embed.FS,即使是这三个类型的别名也不行。
我测试过几个能想到的场景,有些会报错,所以在使用时需要注意。

copy
package main import ( _ "embed" ) //go:embed test.txt var testString string // 当前目录,解析为string类型 //go:embed test.txt var testByte []byte // 当前目录,解析为[]byte类型 //go:embed test/test.txt var testAbsolutePath string // 子目录,解析为string类型 //go:embed notExistsFile var testErr0 string // 文件不存在,编译报错:pattern notExistsFile: no matching files found //go:embed dir var testErr1 string // dir是目录,编译报错:pattern dir: cannot embed directory dir: contains no embeddable files //go:embed ../test.txt var testErr2 string // 相对路径,不是当前目录或子目录,编译报错:pattern ../test.txt: invalid pattern syntax //go:embed D:\test.txt var testErr3 string // 绝对路径,编译报错:pattern D:\test.txt: no matching files found func main() { println(testString) println(string(testByte)) println(testAbsolutePath) }

嵌入文件列表

copy
package main import ( "embed" "io" "os" ) //go:embed test0.txt test1.txt test1*.txt //go:embed test/test0.txt test/test1.txt //go:embed test0 var fileList embed.FS /* 使用上述方法可以将多个文件或目录添加到fileList中。 1. 添加多个文件,且支持"*"号通配文件。 2. 支持子目录文件。 3. 支持嵌入一个目录。 */ func main() { testDir, err := fileList.ReadDir("test0") if err != nil { panic(err) } for _, v := range testDir { println(v.Name()) // 打印嵌入的目录内容 } // 使用fileList.Open可以生成一个对象,可以通过文件流那样读出来 testFile, err := fileList.Open("test0.txt") if err != nil { panic(err) } io.Copy(os.Stdout, testFile) testFile, err = fileList.Open("test112.txt") if err != nil { panic(err) } io.Copy(os.Stdout, testFile) testFile, err = fileList.Open("test/test1.txt") if err != nil { panic(err) } io.Copy(os.Stdout, testFile) // 直接将文件内容读出来 data, err := fileList.ReadFile("test111.txt") if err != nil { panic(err) } println(string(data)) }

嵌入http服务器

以前都需要将http服务器和文件都部署,现在可以直接使用,而且也超级方便。

copy
package main import ( "embed" "net/http" ) //go:embed test0.txt test1.txt test1*.txt //go:embed test/test0.txt test/test1.txt //go:embed test0 var fileList embed.FS func main() { http.Handle("/", http.FileServer(http.FS(fileList))) http.ListenAndServe(":8080", nil) }

下面是web访问结果:

总结

今天看到go1.16发布,看了下特性,支持嵌入文件到可执行程序中,所以研究了一下。
我发现直接看源码的_test测试文件就知道是如何使用的,都不需要到处搜教程。
所以说学习要知其然且知其所以然,不然天天搜别人的示例代码,却不知道原理,是不能灵活使用的。

posted @   janbar  阅读(1449)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~

FAVOURITE

点击右上角即可分享
微信分享提示
*✧⁺˚⁺ପ(๑・ω・)੭ु⁾⁾ 好好学习天天向上
进入亮色模式
进入亮色模式

FAVOURITE