golangembed是什么

本篇內(nèi)容主要講解“golang embed是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“golang embed是什么”吧!                          

成都創(chuàng)新互聯(lián)公司是一家專注于成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)與策劃設(shè)計,天橋網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:天橋等地區(qū)。天橋做網(wǎng)站價格咨詢:18980820575

embed是什么

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

為什么需要embed

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

結(jié)果往往一把二進制文件挪來挪去,就無法把應(yīng)用程序運行起來了,因為無法讀取到靜態(tài)文件的資源。

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

  • 第一種是識別這類靜態(tài)資源,是否需要跟著程序走。

  • 第二種就是將其打包進二進制文件中。

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

但是在Go1.16起,Go語言自身正式支持了該項特性。

它有以下優(yōu)點

  • 能夠?qū)㈧o態(tài)資源打包到二進制包中,部署過程更簡單。傳統(tǒng)部署要么需要將靜態(tài)資源與已編譯程序打包在一起上傳,或者使用dockerdockerfile自動化前者,這是很麻煩的。

  • 確保程序的完整性。在運行過程中損壞或丟失靜態(tài)資源通常會影響程序的正常運行。

  • 靜態(tài)資源訪問沒有io操作,速度會非???/strong>。

embed基礎(chǔ)用法

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

特別注意:embed這個包一定要導(dǎo)入,如果導(dǎo)入不使用的話,使用 _ 導(dǎo)入即可

一、嵌入為字符串

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

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

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

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

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

比如嵌入一個文件:

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

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

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。兩者結(jié)合起來可以像之前操作普通文件一樣。

一、只讀

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

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

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

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

當(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)也采用這個模式。

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

在我們的項目中,是將應(yīng)用的常用的一些配置寫在了.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是什么”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

標題名稱:golangembed是什么
當(dāng)前路徑:http://www.muchs.cn/article18/jiojdp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊商城網(wǎng)站、虛擬主機、品牌網(wǎng)站設(shè)計、微信公眾號、品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)