embed是啥?Go怎么用它加载静态文件?

embed是啥?Go怎么用它加载静态文件?

浏览次数:1132次
信息来源: 银河系资源网
更新日期: 2022-05-14
文章简介

本文由go语言教程栏目给大家介绍Golang1.16怎么使用embed加载静态文件 ,希望对需要的朋友有所帮助! embed是什么embed是在Go ...

本文由go语言教程栏目给大家介绍Golang1.16怎么使用embed加载静态文件 ,希望对需要的朋友有所帮助!

embed是什么

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

为什么需要embed

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

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

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

  • 第一种是识别这类静态资源,是否需要跟着程序走。
  • 第二种就是将其打包进二进制文件中。

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

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

它有以下优点

  • 能够将静态资源打包到二进制包中,部署过程更简单。传统部署要么需要将静态资源与已编译程序打包在一起上传,或者使用dockerdockerfile自动化前者,这是很麻烦的。
  • 确保程序的完整性。在运行过程中损坏或丢失静态资源通常会影响程序的正常运行。
  • 静态资源访问没有io操作,速度会非常快

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)}

以上就是embed是啥?Go怎么用它加载静态文件?的详细内容

标签: 暂无标签
php for循环有几种写法
« 上一篇
php 只能上传1k内的文件怎么办
下一篇 »
  • php 怎么将json数据转成utf8
    45056阅读
    php将json数据转成utf8的方法:1、创建一个PHP示例文件;2、通过“json_encode($xm_json,JSON_UNESCAPED_UNICODE);”将json数组保存为utf8即可。本文操作环境:windows7系统、PHP7.1版、DELL G3电脑php 怎么将json数...
  • php安装 liunx参数有哪些
    6361阅读
    Linux安装PHP配置参数有:1、“--prefix”;2、“--with-config-file-path”;3、“--with-MySQL”;4、“--enable-safe-mode”;5、“--enable-zip”等等。本文操作环境:linux5.9.8系统、PHP7.1版、DELL G3电脑php...
  • php图片显示一片乱码怎么办
    2294阅读
    php图片显示一片乱码的解决办法:1、打开相应的PHP代码文件;2、在页面头部加上“header("Content-Type:image/jpg");”代码声明图片类型即可。本文操作环境:windows7系统、PHP7.1版、DELL G3电脑php图片显示一片乱码...
  • 如何解决php 长度不足问题
    2276阅读
    php长度不足的解决办法:1、创建一个PHP示例文件;2、通过“str_pad($value,2,0,STR_PAD_LEFT);”方式实现字符串固定长度不够补充其他字符串即可。本文操作环境:windows7系统、PHP7.1版、DELL G3电脑如何解决php 长...
  • php sql 字符串怎么转日期
    2099阅读
    php sql字符串转日期的方法:1、通过“date("Y-m-d",strtotime(""));”方式转换;2、通过“date("M-d-Y",mktime(0,0,0,$month,$day,$year));”方式转换。本文操作环境:windows7系统、PHP7.1版、DELL G3电脑php sql ...
  • 看看PHP有哪四种方法实现交换两个整型变量
    2089阅读
    看看PHP有哪四种方法实现交换两个整型变量?交换两个整型变量使用一个中间变量这种是最容易理解的$a = 1; $b = 2; $temp = $a; $a = $b; $b = $temp; var_dump($a, $b);不使用中间变量,就靠几次加减巧妙转换$a = 10...
  • php数组怎么求平均值
    1963阅读
    php数组求平均值的方法:1、用array_sum()计算数组中所有元素之和,语法“array_sum($arr)”;2、用count()获取数组中的元素个数,语法“count($arr)”;3、用“元素和/元素个数”语句计算出数组平均值。本教程操作环...
  • php 怎么判断错误次数
    1870阅读
    php判断错误次数的实现方法:1、实例化redis数据库;2、模拟数据库信息;3、接受用户输入信息;4、判断信息输入错误的次数即可。本文操作环境:Windows7系统、PHP7.1版、DELL G3电脑php 怎么判断错误次数?php 结合r...
  • php怎么实现点击删除代码
    1863阅读
    php实现点击删除代码的方法:1、创建一个PHP示例文件,并连接数据库;2、查询数据库;3、在超链接删除处调用javascript方法,并传递记录id即可。本文操作环境:windows7系统、PHP7.1版、DELL G3电脑php怎么实现点击删...
  • php 怎么把网页转换成图片格式
    1814阅读
    php把网页转换成图片格式的方法:1、装chrome-php/chrome;2、安装chromium;3、通过控制器实现转换逻辑即可。php 怎么把网页转换成图片格式?PHP将整个网页html转换为图片并保存【含滚屏】1、安装chrome-php/chrome...

如本文对您有帮助,随意赞赏一下!