Go1.16新特性embed打包靜態(tài)資源文件實(shí)現(xiàn)
背景
相信有一部分人喜愛 GO 的初衷大概是:跨平臺靜態(tài)編譯,如果在沒用通過 CGO 引用其他庫的話,一般編譯出來的可執(zhí)行二進(jìn)制文件部署起來非常方便,但人們在實(shí)際中發(fā)現(xiàn),使用 Go 語言開發(fā)的后端 WEB 程序存在 HTML 模版、圖片、JS、CSS、JSON 等靜態(tài)資源,部署時需要把這些靜態(tài)資源與二進(jìn)制程序一起上傳到服務(wù)器部署,在現(xiàn)今遍地花容器的今天,為了簡化部署流程,能不能更進(jìn)一步的把這些靜態(tài)文件與二進(jìn)制程序一起打包起來部署,那樣豈不是更方便?對運(yùn)維來說打包一體化帶來的好處就是運(yùn)維復(fù)雜度的降低,對技術(shù)團(tuán)隊(duì)來說打包一體化還可以保證程序完整性可控性。
因此,GO 社區(qū)發(fā)起了一個期望 Go 編譯器支持嵌入靜態(tài)文件的提案issue#35950?,F(xiàn)在,這個功能將隨著 1.16 版本一起發(fā)布,目前最新的版本是 Go 1.16 RC1 預(yù)覽版。
好了,接下來我們詳細(xì)介紹 go embed 的各個功能。
embed 嵌入
└── cmd 測試目錄
├── assets 靜態(tài)資源目錄
│?? ├── .idea.txt
│?? ├── golang.txt
│?? └── hello.txt
└── main.go 測試go源文件
字符串、字節(jié)切片、文件嵌入
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed指令用來嵌入,必須緊跟著嵌入后的變量名
//只支持嵌入為string, byte slice和embed.FS三種類型,這三種類型的別名(alias)和命名類型(如type S string)都不可以
//以字符串形式嵌入 assets/hello.txt
//go:embed assets/hello.txt
var s string
//文件的內(nèi)容嵌入為slice of byte,也就是一個字節(jié)數(shù)組
//go:embed assets/hello.txt
var b []byte
//嵌入為一個文件系統(tǒng) 新的文件系統(tǒng)FS
//go:embed assets/hello.txt
//go:embed assets/golang.txt
var f embed.FS
func main() {
fmt.Println("embed string.", s)
fmt.Println("embed byte.", string(b))
data, _ := f.ReadFile("assets/hello.txt")
fmt.Println("embed fs.", string(data))
data, _ = f.ReadFile("assets/golang.txt")
fmt.Println("embed fs.", string(data))
}
編譯運(yùn)行后輸出:
embed string. hello golang!
embed byte. hello golang!
embed fs. hello golang!
embed fs. hello!
從上面的代碼可以看出,embed 支持嵌入為 string,byte slice 和 embed.FS 這三種類型,另外也不允許從這些類型中派生哦。
嵌入文件
對于 FS 類型的嵌入,也可以支持一個變量嵌入多個文件。
//go:embed assets/hello.txt //go:embed assets/golang.txt var f embed.FS
當(dāng)然也支持,兩個變量嵌入一個文件。雖然兩個變量嵌入了同一個文件,但它們在編譯的時候會獨(dú)立分配,彼此之間并不會互相影響。
嵌入文件夾
FS 類型的嵌入支持文件夾.分隔符采用正斜杠/,即使是 windows 系統(tǒng)也采用這個模式。
//go:embed assets
var f embed.FS
func main() {
data, _ := f.ReadFile("assets/hello.txt")
fmt.Println(string(data))
}
嵌入匹配
go:embed 指令中可以只寫文件夾名,此文件夾中除了.和_開頭的文件和文件夾都會被嵌入,并且子文件夾也會被遞歸的嵌入,形成一個此文件夾的文件系統(tǒng)。
如果想嵌入.和_開頭的文件和文件夾, 比如.hello.txt 文件,那么就需要使用*,比如 go:embed assets/*。
不具有遞歸性,所以子文件夾下的.和_不會被嵌入,除非你在專門使用子文件夾的進(jìn)行嵌入:
├── assets
│?? ├── .idea.txt
│?? ├── golang.txt
│?? └── hello.txt
└── main.go
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed assets/*
var f embed.FS
func main() {
data, _ := f.ReadFile("assets/.idea.txt")
fmt.Println(string(data))
}
FS 文件系統(tǒng)
embed.FS 實(shí)現(xiàn)了 io/fs.FS 接口,它可以打開一個文件,返回 fs.File:
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed assets
var f embed.FS
func main() {
helloFile, _ := f.Open("assets/hello.txt")
stat, _ := helloFile.Stat()
fmt.Println(stat.Name(), stat.Size())
}
它還提供了 ReadFileh 和 ReadDir 功能,遍歷一個文件下的文件和文件夾信息:
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed assets
var f embed.FS
func main() {
dirEntries, _ := f.ReadDir("assets")
for _, de := range dirEntries {
fmt.Println(de.Name(), de.IsDir())
}
}
因?yàn)樗鼘?shí)現(xiàn)了 io/fs.FS 接口,所以可以返回它的子文件夾作為新的文件系統(tǒng):
package main
import (
"embed"
_ "embed"
"fmt"
"io/fs"
"io/ioutil"
)
//go:embed assets
var f embed.FS
func main() {
as, _ := fs.Sub(f, "assets")
hi, _ := as.Open("hello.txt")
data, _ := ioutil.ReadAll(hi)
fmt.Println(string(data))
}
總結(jié):
- 對于單個的文件,支持嵌入為字符串和 byte slice
- 對于多個文件和文件夾,支持嵌入為新的文件系統(tǒng) FS
- go:embed 指令用來嵌入,必須緊跟著嵌入后的變量名
- 只支持嵌入為 string, byte slice 和 embed.FS 三種類型,類型派生也不可以。
以上就是Go 1.16新特性embed打包靜態(tài)資源文件實(shí)現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Go embed打包靜態(tài)資源的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang創(chuàng)建文件目錄os.Mkdir,os.MkdirAll的區(qū)別說明
本文主要講述os.Mkdir、os.MkdirAll區(qū)別以及在創(chuàng)建文件目錄過程中的一些其他技巧,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
golang用melody搭建輕量的websocket服務(wù)的示例代碼
在Go中,可以使用gin和melody庫來搭建一個輕量級的WebSocket服務(wù),gin是一個流行的Web框架,而melody是一個用于處理WebSocket的庫,本文給大家演示如何使用gin和melody搭建WebSocket服務(wù),感興趣的朋友一起看看吧2023-10-10
golang 對私有函數(shù)進(jìn)行單元測試的實(shí)例
這篇文章主要介紹了golang 對私有函數(shù)進(jìn)行單元測試的實(shí)例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
關(guān)于golang中map使用的幾點(diǎn)注意事項(xiàng)總結(jié)(強(qiáng)烈推薦!)
map是一種無序的基于key-value的數(shù)據(jù)結(jié)構(gòu),Go語言中的map是引用類型,必須初始化才能使用,下面這篇文章主要給大家介紹了關(guān)于golang中map使用的幾點(diǎn)注意事項(xiàng),需要的朋友可以參考下2023-01-01

