文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

golang embed是什么

2023-06-25 15:00

关注

本篇内容主要讲解“golang embed是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“golang embed是什么”吧!                          

embed是什么

embed是在Go 1.16中新加入的包。它通过//go:embed指令,可以在编译阶段将静态资源文件打包进编译好的程序中,并提供访问这些文件的能力。

为什么需要embed

在以前,很多从其他语言转过来Go语言的小伙伴会问到,或者踩到一个坑:就是以为Go语言所打包的二进制文件中会包含配置文件的联同编译和打包。

结果往往一把二进制文件挪来挪去,就无法把应用程序运行起来了,因为无法读取到静态文件的资源。

无法将静态资源编译打包二进制文件的话,通常会有两种解决方法:

第二种情况的话,Go以前是不支持的,大家就会借助各种花式的开源库,例如:go-bindata/go-bindata来实现。

但是在Go1.16起,Go语言自身正式支持了该项特性。

它有以下优点

embed基础用法

通过 官方文档 我们知道embed嵌入的三种方式:string、bytes 和 FS(File Systems)。其中string[]byte类型都只能匹配一个文件,如果要匹配多个文件或者一个目录,就要使用embed.FS类型。

特别注意:embed这个包一定要导入,如果导入不使用的话,使用 _ 导入即可

一、嵌入为字符串

比如当前文件下有个hello.txt的文件,文件内容为hello,world!。通过go:embed指令,在编译后下面程序中的s变量的值就变为了hello,world!

package mainimport (    _ "embed"    "fmt")//go:embed hello.txtvar s stringfunc main() {    fmt.Println(s)}
二、嵌入为byte slice

你还可以把单个文件的内容嵌入为slice of byte,也就是一个字节数组。

package mainimport (    _ "embed"    "fmt")//go:embed hello.txtvar b []bytefunc main() {    fmt.Println(b)}
三、嵌入为fs.FS

甚至你可以嵌入为一个文件系统,这在嵌入多个文件的时候非常有用。

比如嵌入一个文件:

package mainimport (    "embed"    "fmt")//go:embed hello.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("hello.txt")    fmt.Println(string(data))}

嵌入本地的另外一个文件hello2.txt, 支持同一个变量上多个go:embed指令(嵌入为string或者byte slice是不能有多个go:embed指令的):

package mainimport (    "embed"    "fmt")//go:embed hello.txt//go:embed hello2.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("hello.txt")    fmt.Println(string(data))    data, _ = f.ReadFile("hello2.txt")    fmt.Println(string(data))}

当前重复的go:embed指令嵌入为embed.FS是支持的,相当于一个:

package mainimport (    "embed"    "fmt")//go:embed hello.txt//go:embed hello.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("hello.txt")    fmt.Println(string(data))}

还可以嵌入子文件夹下的文件:

package mainimport (    "embed"    "fmt")//go:embed p/hello.txt//go:embed p/hello2.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("p/hello.txt")    fmt.Println(string(data))    data, _ = f.ReadFile("p/hello2.txt")    fmt.Println(string(data))}

embed进阶用法

Go1.16 为了对 embed 的支持也添加了一个新包 io/fs。两者结合起来可以像之前操作普通文件一样。

一、只读

嵌入的内容是只读的。也就是在编译期嵌入文件的内容是什么,那么在运行时的内容也就是什么。

FS文件系统值提供了打开和读取的方法,并没有write的方法,也就是说FS实例是线程安全的,多个goroutine可以并发使用。

embed.FS结构主要有3个对外方法,如下:

// Open 打开要读取的文件,并返回文件的fs.File结构.func (f FS) Open(name string) (fs.File, error)// ReadDir 读取并返回整个命名目录func (f FS) ReadDir(name string) ([]fs.DirEntry, error)// ReadFile 读取并返回name文件的内容.func (f FS) ReadFile(name string) ([]byte, error)
二、嵌入多个文件

package mainimport (    "embed"    "fmt")//go:embed hello.txt hello2.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("hello.txt")    fmt.Println(string(data))    data, _ = f.ReadFile("hello2.txt")    fmt.Println(string(data))}

当然你也可以像前面的例子一样写成多行go:embed:

package mainimport (    "embed"    "fmt")//go:embed hello.txt//go:embed hello2.txtvar f embed.FSfunc main() {    data, _ := f.ReadFile("hello.txt")    fmt.Println(string(data))    data, _ = f.ReadFile("hello2.txt")    fmt.Println(string(data))}
三、支持文件夹

文件夹分隔符采用正斜杠/,即使是windows系统也采用这个模式。

package mainimport (    "embed"    "fmt")//go:embed pvar f embed.FSfunc main() {    data, _ := f.ReadFile("p/hello.txt")    fmt.Println(string(data))    data, _ = f.ReadFile("p/hello2.txt")    fmt.Println(string(data))}

应用

在我们的项目中,是将应用的常用的一些配置写在了.env的一个文件上,所以我们在这里就可以使用go:embed指令。

main.go 文件:

//go:embed ".env" "v1d0/.env"var FS embed.FSfunc main(){    setting.InitSetting(FS)    manager.InitManager()    cron.InitCron()    routersInit := routers.InitRouter()    readTimeout := setting.ServerSetting.ReadTimeout    writeTimeout := setting.ServerSetting.WriteTimeout    endPoint := fmt.Sprintf(":%d", setting.ServerSetting.HttpPort)    maxHeaderBytes := 1 << 20    server := &http.Server{        Addr:           endPoint,        Handler:        routersInit,        ReadTimeout:    readTimeout,        WriteTimeout:   writeTimeout,        MaxHeaderBytes: maxHeaderBytes,    }    server.ListenAndServe()}

setting.go文件:

func InitSetting(FS embed.FS) {    // 总配置处理    var err error    data, err := FS.ReadFile(".env")    if err != nil {        log.Fatalf("Fail to parse '.env': %v", err)    }    cfg, err = ini.Load(data)    if err != nil {        log.Fatal(err)    }    mapTo("server", ServerSetting)    ServerSetting.ReadTimeout  = ServerSetting.ReadTimeout * time.Second    ServerSetting.WriteTimeout = ServerSetting.WriteTimeout * time.Second    // 分版本配置引入    v1d0Setting.InitSetting(FS)}

到此,相信大家对“golang embed是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯