網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
背景
相信有一部分人喜愛 GO 的初衷大概是:跨平臺(tái)靜態(tài)編譯,如果在沒用通過(guò) CGO 引用其他庫(kù)的話,一般編譯出來(lái)的可執(zhí)行二進(jìn)制文件部署起來(lái)非常方便,但人們?cè)趯?shí)際中發(fā)現(xiàn),使用 Go 語(yǔ)言開發(fā)的后端 WEB 程序存在 HTML 模版、圖片、JS、CSS、JSON 等靜態(tài)資源,部署時(shí)需要把這些靜態(tài)資源與二進(jìn)制程序一起上傳到服務(wù)器部署,在現(xiàn)今遍地花容器的今天,為了簡(jiǎn)化部署流程,能不能更進(jìn)一步的把這些靜態(tài)文件與二進(jìn)制程序一起打包起來(lái)部署,那樣豈不是更方便?對(duì)運(yùn)維來(lái)說(shuō)打包一體化帶來(lái)的好處就是運(yùn)維復(fù)雜度的降低,對(duì)技術(shù)團(tuán)隊(duì)來(lái)說(shuō)打包一體化還可以保證程序完整性可控性。
因此,GO 社區(qū)發(fā)起了一個(gè)期望 Go 編譯器支持嵌入靜態(tài)文件的提案issue#35950。現(xiàn)在,這個(gè)功能將隨著 1.16 版本一起發(fā)布,目前最新的版本是 Go 1.16 RC1 預(yù)覽版。
好了,接下來(lái)我們?cè)敿?xì)介紹 go embed 的各個(gè)功能。
embed 嵌入
└── cmd 測(cè)試目錄
├── assets 靜態(tài)資源目錄
│?? ├── .idea.txt
│?? ├── golang.txt
│?? └── hello.txt
└── main.go 測(cè)試go源文件
字符串、字節(jié)切片、文件嵌入
package main import ( "embed" _ "embed" "fmt" ) //go:embed指令用來(lái)嵌入,必須緊跟著嵌入后的變量名 //只支持嵌入為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,也就是一個(gè)字節(jié)數(shù)組 //go:embed assets/hello.txt var b []byte //嵌入為一個(gè)文件系統(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 這三種類型,另外也不允許從這些類型中派生哦。
嵌入文件
對(duì)于 FS 類型的嵌入,也可以支持一個(gè)變量嵌入多個(gè)文件。
//go:embed assets/hello.txt //go:embed assets/golang.txt var f embed.FS
當(dāng)然也支持,兩個(gè)變量嵌入一個(gè)文件。雖然兩個(gè)變量嵌入了同一個(gè)文件,但它們?cè)诰幾g的時(shí)候會(huì)獨(dú)立分配,彼此之間并不會(huì)互相影響。
嵌入文件夾
FS 類型的嵌入支持文件夾.分隔符采用正斜杠/,即使是 windows 系統(tǒng)也采用這個(gè)模式。
//go:embed assets var f embed.FS func main() { data, _ := f.ReadFile("assets/hello.txt") fmt.Println(string(data)) }
嵌入匹配
go:embed 指令中可以只寫文件夾名,此文件夾中除了.和_開頭的文件和文件夾都會(huì)被嵌入,并且子文件夾也會(huì)被遞歸的嵌入,形成一個(gè)此文件夾的文件系統(tǒng)。
如果想嵌入.和_開頭的文件和文件夾, 比如.hello.txt 文件,那么就需要使用*,比如 go:embed assets/*。
不具有遞歸性,所以子文件夾下的.和_不會(huì)被嵌入,除非你在專門使用子文件夾的進(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 接口,它可以打開一個(gè)文件,返回 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 功能,遍歷一個(gè)文件下的文件和文件夾信息:
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é):
- 對(duì)于單個(gè)的文件,支持嵌入為字符串和 byte slice
- 對(duì)于多個(gè)文件和文件夾,支持嵌入為新的文件系統(tǒng) FS
- go:embed 指令用來(lái)嵌入,必須緊跟著嵌入后的變量名
- 只支持嵌入為 string, byte slice 和 embed.FS 三種類型,類型派生也不可以。
原文鏈接:https://xie.infoq.cn/article/0e69354f6d1c866193f76cea9
相關(guān)推薦
- 2022-07-04 解決Python保存文件名太長(zhǎng)OSError:?[Errno?36]?File?name?too?l
- 2022-04-16 統(tǒng)計(jì)C語(yǔ)言二叉樹中葉子結(jié)點(diǎn)個(gè)數(shù)_C 語(yǔ)言
- 2021-12-06 centos7.6批量增加修改刪除虛擬網(wǎng)卡操作介紹_Linux
- 2023-02-01 Bat腳本之在文件中查找多個(gè)字符串并保存到文件中_DOS/BAT
- 2022-07-15 SQL?Server分頁(yè)方法匯總_MsSql
- 2022-05-28 Python讀取文件的四種方式的實(shí)例詳解_python
- 2022-02-13 自動(dòng)化進(jìn)行Pod的擴(kuò)縮容-HPA
- 2022-12-11 React?state狀態(tài)屬性用法講解_React
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支