当前位置: 首页 > 科技观察

Go1.16新特性:一篇文章快速上手Goembed

时间:2023-03-16 17:27:13 科技观察

本文转载自微信公众号《我的大脑是炸鱼》,作者陈建宇。转载本文请联系脑筋急转弯公众号。大家好,我是痴迷于学习炸鱼的建宇。以前很多从其他语言转Go语言的同学都会问,或者踩坑。以为Go语言打包的二进制文件会包含配置文件的联合编译打包。因此,移动二进制文件后通常无法运行应用程序。因为无法读取静态文件的资源。如果静态资源不能编译打包成二进制文件,通常有两种解决方法:第一种是识别这种静态资源,是否需要跟在程序后面。二是考虑打包成二进制文件。第二种情况,Go之前是不支持的,大家会用各种花哨的开源库,比如:go-bindata/go-bindata来实现。但是从Go1.16开始,Go语言本身就正式支持了这个特性。今天我们就通过这篇文章来快速了解和学习这个特性。基本使用演示代码:import_"embed"//go:embedhello.txtvarsstringfuncmain(){print(s)}我们先在对应目录下新建一个hello.txt文件,写入文本内容“吃炸鱼”。核心的//go:embedhello.txt注解写在代码中。注解的格式很简单,就是go:embed指令声明,加上读取内容的地址,支持相对路径和绝对路径。输出结果:吃炸鱼读取静态文件中的内容,自动赋值给变量s,在main函数中成功输出。对于其他基本类型,Goembed还支持://go:embedhello.txtvarsstring//go:embedhello.txtvarb[]byte//go:embedhello.txtvarfembed.FSfuncmain(){print(s)print(string(b))data,_:=f.ReadFile("hello.txt")print(string(data))}输出结果:吃炸鱼,吃炸鱼,吃炸鱼我们在一个代码文件中同时进行了多次嵌入的注解语句。并且针对string、slice、byte、fs等各种类型进行了封装,不需要过多的处理,非常方便。除了扩展用法的基本用法,embed本身还支持命令中的多种变形://go:embedhello1.txtvarfembed.FSfuncmain(){data1,_:=f.ReadFile("hello1.txt")fmt.Println(string(data1))data2,_:=f.ReadFile("hello2.txt")fmt.Println(string(data2))}在指定go:embed注解时可以一次读取多个文件,也是一个变量可以多行注释://go:embedhello1.txt//go:embedhello2.txtvarfembed.FS也可以在注释中指定目录helloworld,然后读取对应的文件://go:embedhelloworldvarfembed.FSfuncmain(){data1,_:=f.ReadFile("helloworld/hello1.txt")fmt.Println(string(data1))data2,_:=f.ReadFile("helloworld/hello2.txt")fmt.Println(string(data2))}同时,由于可以支持目录读取,所以也可以支持贪心模式匹配://go:embedhelloworld/*varfembed.FS可能有小伙伴注意到embed.FS还可以调整各种文件系统的接口.其实本质就是embed.FS实现了io/fs接口。只读属性在embed提供的FS中,我们可以发现它是打开的,只读的:typeFSfunc(fFS)Open(namestring)(fs.File,error)func(fFS)ReadDir(namestring)([]fs.DirEntry,error)func(fFS)ReadFile(namestring)([]byte,error)据此也可以判断打包进embed的二进制文件内容只允许读取不允许读取被改变。更抽象的说,embed的内容在编译时就确定了,运行时不允许修改,保证了一致性。总结通过Go1.16官方提供的embed特性,可以原生实现静态资源文件的嵌入。整体如下:功能方面:可以在二进制文件中嵌入静态资源,相关打包的静态文件可以在运行时打开读取。安全性方面:编译时编译嵌入,不支持运行时修改。使用中:支持单文件阅读:go:embedhello.txt。支持多文件阅读:go:embedhello1.txt、go:embedhello2.txt。支持目录读取:go:embedhelloworld。支持贪心匹配:go:embedhelloworld/*。总的来说,Go1.16的embed特性填补了Go语言在静态文件资源打包方面的一个原生空白。同时也说明Go官方确实在不断的从社区吸收一些好的想法和经验。