Go1.16 新特性:一文快速上手 Go embed
· · 222 次点击 ·
·
开始浏览
在以前,很多从其他语言转过来 Go 语言的同学会问到,或是踩到一个坑。就是以为 Go 语言所打包的二进制文件中会包含配置文件的联同编译和打包。
结果往往一把二进制文件挪来挪去,就无法把应用程序运行起来了。因为无法读取到静态文件的资源。
无法将静态资源编译打包进二进制文件的话,通常会有两种解决方法:
第二种情况的话,Go 以前是不支持的,大家就会去借助各种花式的开源库,例如:go-bindata/go-bindata 来实现。
但从在 Go1.16 起,Go 语言自身正式支持了该项特性,今天我们将通过这篇文章快速了解和学习这项特性。
演示代码:
import _ "embed" //go:embed hello.txt var s string func main() { print(s)
我们首先在对应的目录下创建了 hello.txt 文件,并且写入文本内容 “吃煎鱼”。
在代码中编写了最为核心的 //go:embed hello.txt 注解。注解的格式很简单,就是 go:embed 指令声明,外加读取的内容的地址,可支持相对和绝对路径。
输出结果:
吃煎鱼
读取到静态文件中的内容后自动赋值给了变量 s,并且在主函数中成功输出。
而针对其他的基础类型,Go embed 也是支持的:
//go:embed hello.txt var s string //go:embed hello.txt var b []byte //go:embed hello.txt var f embed.FS func main() { print(s) print(string(b)) data, _ := f.ReadFile("hello.txt") print(string(data))
输出结果:
吃煎鱼
我们同时在一个代码文件中进行了多个 embed 的注解声明。
并且针对 string、slice、byte、fs 等多种类型进行了打包,也不需要过多的处理,非常便利。
除去基本用法完,embed 本身在指令上也支持多种变形:
//go:embed hello1.txt hello2.txt var f embed.FS func main() { data1, _ := f.ReadFile("hello1.txt") fmt.Println(string(data1)) data2, _ := f.ReadFile("hello2.txt") fmt.Println(string(data2))
在指定 go:embed 注解时可以一次性多个文件来读取,并且也可以一个变量多行注解:
//go:embed hello1.txt //go:embed hello2.txt var f embed.FS
也可以通过在注解中指定目录 helloworld,再对应读取文件:
//go:embed helloworld var f embed.FS func main() { data1, _ := f.ReadFile("helloworld/hello1.txt") fmt.Println(string(data1)) data2, _ := f.ReadFile("helloworld/hello2.txt") fmt.Println(string(data2))
同时既然能够支持目录读取,也能支持贪婪模式的匹配:
//go:embed helloworld/* var f embed.FS
可能会有小伙伴注意到,embed.FS 也能调各类文件系统的接口,其实本质是 embed.FS 实现了 io/fs 接口。
在 embed 所提供的 FS 中,我们可以发现其都是打开和只读方法:
type FS func (f FS) Open(name string) (fs.File, error) func (f FS) ReadDir(name string) ([]fs.DirEntry, error) func (f FS) ReadFile(name string) ([]byte, error)
根据此也可以确定 embed 所打包进二进制文件的内容只允许读取,不允许变更。
更抽象来讲就是在编译期就确定了 embed 的内容,在运行时不允许修改,保证了一致性。
通过 Go1.16 正式提供的 embed 特性,可以实现原生就支持静态资源文件的嵌入。整体如下:
在功能上:能够将静态资源嵌入二进制文件中,在运行时可以打开和读取相关的打包后的静态文件。
总的来讲,Go1.16 embed 特性很好的填补了 Go 语言在打包静态文件资源的一块原生空白领域。同时也说明了 Go 官方的确在不断地吸收社区的一些良好的想法和经验。
222 次点击
加入收藏
相关文章
- 如何简单粗暴快速的开发一款 Go 博客 - 记Milu博客1.0.beta版本发布
- GOPROXY_go map
- Go语言 参数传递究竟是值传递还是引用传递
- 4.Go编程快速入门学习
- 数据库Go-sqlx实战
- 一个小时学会用 Go 创建命令行工具
- 「Go工具箱」go语言csrf库的使用方式和实现原理
- Go 进阶训练营 – 评论系统架构设计二:详细设计
- 【一Go到底】第六天---值类型、引用类型、标识符
- Go 1.12中出现的top命令RES参数异常增高的问题
- 「Go工具箱」一个对语义化版本进行解析、比较的库:go-version
- 「Go工具箱」redis官网推荐的go版本的分布式锁:redsync
- 2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。
- Go-标准库-bufio(二)
- Go-包管理-go build(一)
- Go-包管理-go install
- go pprof命令(Go语言性能分析命令)完全攻略
- Go语言字符串截取(获取字符串的某一段字符)
- Linux下安装Go环境指南(linux安装go环境)
- Go 通道是糟糕的,你应该也觉得很糟糕
- 以Go语言操作MySQL:轻松运行数据库各种查询(go语言mysql)
- 关键字在SQL Server中利用GO关键字实现更优化的操作(sqlserver中go)
- 使用Go语言实现Redis数据库(用go实现redis)
- Go语言链接Oracle数据库的实践记录(go 链接oracle)
- 部署Go语言快速连接Oracle实现轻松部署(go连接oracle简单)
- Go语言查询Oracle数据库实战实例(go语言查询oracle)
- 新技术Go语言解析Oracle数据库日志(go解析oracle日志)