如有任何問題或建議,歡迎及時交流和碰撞。個人公衆號是 【腦子進煎魚了】,GitHub 地址: https://github.com/eddycjy。
你們好,我是煎魚。git
在之前,不少從其餘語言轉過來 Go 語言的同窗會問到,或是踩到一個坑。就是覺得 Go 語言所打包的二進制文件中會包含配置文件的聯同編譯和打包。github
結果每每一把二進制文件挪來挪去,就沒法把應用程序運行起來了。由於沒法讀取到靜態文件的資源。安全
沒法將靜態資源編譯打包進二進制文件的話,一般會有兩種解決方法:架構
第二種狀況的話,Go 之前是不支持的,你們就會去借助各類花式的開源庫,例如:go-bindata/go-bindata 來實現。函數
但從在 Go1.16 起,Go 語言自身正式支持了該項特性,今天咱們將經過這篇文章快速瞭解和學習這項特性。微服務
演示代碼:學習
import _ "embed" //go:embed hello.txt var s string func main() { print(s) }
咱們首先在對應的目錄下建立了 hello.txt
文件,而且寫入文本內容 「吃煎魚」。spa
在代碼中編寫了最爲核心的 //go:embed hello.txt
註解。註解的格式很簡單,就是 go:embed
指令聲明,外加讀取的內容的地址,可支持相對和絕對路徑。設計
輸出結果:code
吃煎魚
讀取到靜態文件中的內容後自動賦值給了變量 s
,而且在主函數中成功輸出。
而針對其餘的基礎類型,Go embed 也是支持的:
//go:embed hello.txt var s string //go:embed hello.txt var b []byte //go:embed hello.txt var f embed.FS func main() { print(s) print(string(b)) data, _ := f.ReadFile("hello.txt") print(string(data)) }
輸出結果:
吃煎魚 吃煎魚 吃煎魚
咱們同時在一個代碼文件中進行了多個 embed 的註解聲明。
而且針對 string、slice、byte、fs 等多種類型進行了打包,也不須要過多的處理,很是便利。
除去基本用法完,embed 自己在指令上也支持多種變形:
//go:embed hello1.txt hello2.txt var f embed.FS func main() { data1, _ := f.ReadFile("hello1.txt") fmt.Println(string(data1)) data2, _ := f.ReadFile("hello2.txt") fmt.Println(string(data2)) }
在指定 go:embed
註解時能夠一次性多個文件來讀取,而且也能夠一個變量多行註解:
//go:embed hello1.txt //go:embed hello2.txt var f embed.FS
也能夠經過在註解中指定目錄 helloworld
,再對應讀取文件:
//go:embed helloworld var f embed.FS func main() { data1, _ := f.ReadFile("helloworld/hello1.txt") fmt.Println(string(data1)) data2, _ := f.ReadFile("helloworld/hello2.txt") fmt.Println(string(data2)) }
同時既然可以支持目錄讀取,也能支持貪婪模式的匹配:
//go:embed helloworld/* var f embed.FS
可能會有小夥伴注意到,embed.FS
也能調各種文件系統的接口,其實本質是 embed.FS
實現了 io/fs
接口。
在 embed 所提供的 FS 中,咱們能夠發現其都是打開和只讀方法:
type FS func (f FS) Open(name string) (fs.File, error) func (f FS) ReadDir(name string) ([]fs.DirEntry, error) func (f FS) ReadFile(name string) ([]byte, error)
根據此也能夠肯定 embed 所打包進二進制文件的內容只容許讀取,不容許變動。
更抽象來說就是在編譯期就肯定了 embed 的內容,在運行時不容許修改,保證了一致性。
經過 Go1.16 正式提供的 embed 特性,能夠實現原生就支持靜態資源文件的嵌入。總體以下:
在使用上:
go:embed hello.txt
。go:embed hello1.txt
、go:embed hello2.txt
。go:embed helloworld
。go:embed helloworld/*
。總的來說,Go1.16 embed 特性很好的填補了 Go 語言在打包靜態文件資源的一塊原生空白領域。同時也說明了 Go 官方的確在不斷地吸取社區的一些良好的想法和經驗。
分享 Go 語言、微服務架構和奇怪的系統設計,歡迎你們關注個人公衆號和我進行交流和溝通。
最好的關係是互相成就,各位的點贊就是煎魚創做的最大動力,感謝支持。