av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

embed是啥?Go怎么用它加載靜態(tài)文件?

本文由go語(yǔ)言教程欄目給大家介紹Golang1.16怎么使用embed加載靜態(tài)文件 ,希望對(duì)需要的朋友有所幫助!

成都創(chuàng)新互聯(lián)專業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專業(yè)提供成都服務(wù)器托管,服務(wù)器租用,成都棕樹(shù)機(jī)房,成都棕樹(shù)機(jī)房,成都多線服務(wù)器托管等服務(wù)器托管服務(wù)。

embed是什么

embed是在Go 1.16中新加入的包。它通過(guò)//go:embed指令,可以在編譯階段將靜態(tài)資源文件打包進(jìn)編譯好的程序中,并提供訪問(wèn)這些文件的能力。

為什么需要embed

在以前,很多從其他語(yǔ)言轉(zhuǎn)過(guò)來(lái)Go語(yǔ)言的小伙伴會(huì)問(wèn)到,或者踩到一個(gè)坑:就是以為Go語(yǔ)言所打包的二進(jìn)制文件中會(huì)包含配置文件的聯(lián)同編譯和打包。

結(jié)果往往一把二進(jìn)制文件挪來(lái)挪去,就無(wú)法把應(yīng)用程序運(yùn)行起來(lái)了,因?yàn)闊o(wú)法讀取到靜態(tài)文件的資源。

無(wú)法將靜態(tài)資源編譯打包二進(jìn)制文件的話,通常會(huì)有兩種解決方法:

  • 第一種是識(shí)別這類靜態(tài)資源,是否需要跟著程序走。
  • 第二種就是將其打包進(jìn)二進(jìn)制文件中。

第二種情況的話,Go以前是不支持的,大家就會(huì)借助各種花式的開(kāi)源庫(kù),例如:go-bindata/go-bindata來(lái)實(shí)現(xiàn)。

但是在Go1.16起,Go語(yǔ)言自身正式支持了該項(xiàng)特性。

它有以下優(yōu)點(diǎn)

  • 能夠?qū)㈧o態(tài)資源打包到二進(jìn)制包中,部署過(guò)程更簡(jiǎn)單。傳統(tǒng)部署要么需要將靜態(tài)資源與已編譯程序打包在一起上傳,或者使用dockerdockerfile自動(dòng)化前者,這是很麻煩的。
  • 確保程序的完整性。在運(yùn)行過(guò)程中損壞或丟失靜態(tài)資源通常會(huì)影響程序的正常運(yùn)行。
  • 靜態(tài)資源訪問(wèn)沒(méi)有io操作,速度會(huì)非常快。

embed基礎(chǔ)用法

通過(guò) 官方文檔 我們知道embed嵌入的三種方式:string、bytes 和 FS(File Systems)。其中string[]byte類型都只能匹配一個(gè)文件,如果要匹配多個(gè)文件或者一個(gè)目錄,就要使用embed.FS類型。

一、嵌入為字符串

比如當(dāng)前文件下有個(gè)hello.txt的文件,文件內(nèi)容為hello,world!。通過(guò)go:embed指令,在編譯后下面程序中的s變量的值就變?yōu)榱?code>hello,world!。

package mainimport (
    _ "embed"
    "fmt")//go:embed hello.txtvar s stringfunc main() {
    fmt.Println(s)}

二、嵌入為byte slice

你還可以把單個(gè)文件的內(nèi)容嵌入為slice of byte,也就是一個(gè)字節(jié)數(shù)組。

package mainimport (
    _ "embed"
    "fmt")//go:embed hello.txtvar b []bytefunc main() {
    fmt.Println(b)}

三、嵌入為fs.FS

甚至你可以嵌入為一個(gè)文件系統(tǒng),這在嵌入多個(gè)文件的時(shí)候非常有用。

比如嵌入一個(gè)文件:

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

嵌入本地的另外一個(gè)文件hello2.txt, 支持同一個(gè)變量上多個(gè)go:embed指令(嵌入為string或者byte slice是不能有多個(gè)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))}

當(dāng)前重復(fù)的go:embed指令嵌入為embed.FS是支持的,相當(dāng)于一個(gè):

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進(jìn)階用法

Go1.16 為了對(duì) embed 的支持也添加了一個(gè)新包 io/fs。兩者結(jié)合起來(lái)可以像之前操作普通文件一樣。

一、只讀

嵌入的內(nèi)容是只讀的。也就是在編譯期嵌入文件的內(nèi)容是什么,那么在運(yùn)行時(shí)的內(nèi)容也就是什么。

FS文件系統(tǒng)值提供了打開(kāi)和讀取的方法,并沒(méi)有write的方法,也就是說(shuō)FS實(shí)例是線程安全的,多個(gè)goroutine可以并發(fā)使用。

embed.FS結(jié)構(gòu)主要有3個(gè)對(duì)外方法,如下:

// Open 打開(kāi)要讀取的文件,并返回文件的fs.File結(jié)構(gòu).func (f FS) Open(name string) (fs.File, error)// ReadDir 讀取并返回整個(gè)命名目錄func (f FS) ReadDir(name string) ([]fs.DirEntry, error)// ReadFile 讀取并返回name文件的內(nèi)容.func (f FS) ReadFile(name string) ([]byte, error)

二、嵌入多個(gè)文件

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

當(dāng)然你也可以像前面的例子一樣寫成多行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系統(tǒng)也采用這個(gè)模式。

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

應(yīng)用

在我們的項(xiàng)目中,是將應(yīng)用的常用的一些配置寫在了.env的一個(gè)文件上,所以我們?cè)谶@里就可以使用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()}
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)}

網(wǎng)頁(yè)題目:embed是啥?Go怎么用它加載靜態(tài)文件?
本文地址:http://uogjgqi.cn/article/djipojs.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流