embed是go1.16引入的庫,允許我們編譯的時候內(nèi)嵌文件到go的二進(jìn)制文件类少,
最典型的應(yīng)用,就是web服務(wù)器把前端build的二進(jìn)制文件打包到一個二進(jìn)制文件。這樣用起來就很方便图毕。
還有就是把配置文件打包到二進(jìn)制文件之類的。
golang很多官方推出的庫眷唉,未必好用予颤,功能也不是最全的。
比如zip壓縮就不是很好用冬阳,還有就是文件匹配的glob蛤虐,它不支持**
語法
這個embed就有一些問題
這次我碰到了embed失效的問題。
go這類注釋來表示的指令我之前其實沒用過肝陪,雖然知道go generate這個指令但是并沒有用過驳庭。
embed之前我在內(nèi)嵌html文件的時候用過,那時候發(fā)現(xiàn)的問題是氯窍,好像只能在根路徑使用(因為我的web的目錄在根路徑)饲常,因為好像不支持父級的相對路徑捏检,這個就導(dǎo)致難用,因為我本來想把這個內(nèi)嵌寫在router包里面的不皆。
但是現(xiàn)在發(fā)現(xiàn)embed似乎是支持父級相對路徑的
只是下面的不會生效贯城,會報錯
//go:embed ../test.txt
但是路徑分隔符用反斜杠就沒問題了。
//go:embed ..\test.txt
還有這次我碰到的指令不生效的問題
是因為指令和注釋最大的區(qū)別是霹娄, 指令是//go:
,也就是說不能有空格能犯,有空格的會被當(dāng)做注釋處理。
也就是官方只是匹配//go:指令
這樣的前綴來解析指令犬耻。
// go:embed ..\test.txt
還有一個注意點是
embed只在package級別生效踩晶,也就是說在函數(shù)內(nèi)的注釋是不管的。
其他解決方案
最近給項目寫了github action枕磁,用于提交新版本tag的時候渡蜻,自動發(fā)布新版本。
然后發(fā)現(xiàn)我的項目在linux下編譯報錯了计济。
雖然我在windows本地的時候編譯沒有問題茸苇,
這時我發(fā)現(xiàn)那個父級目錄的用法,應(yīng)該是有問題的沦寂,至少在linux下編譯會失敗学密。。传藏。
然后我就翻了github的issue腻暮,沒有找到很好的解決方案。
因為我把配置文件放在根目錄毯侦,也就是和main文件在同一個目錄哭靖。所以沒有什么好的方法。
也不能從main中導(dǎo)入侈离,那樣會有循環(huán)依賴的問題试幽。。霍狰。
最后我從go github issue中找到兩種方法
go generate
這個方法給人感覺就比較蠢抡草,總之就是把文件拷貝到同級目錄就沒事了。
簡單粗暴的方法
//go:generate cp -r ../../assets ./local-asset-dir
//go:embed local-asset-dir
var assetFs embed.FS
創(chuàng)建一個package蔗坯,把文件放到這個package目錄中
其實和上面的方法是一樣的康震,甚至某種程度上還不如。
上面的方法宾濒,至少還能自由選擇文件的位置腿短。
最后我選擇這種方法,創(chuàng)建一個package,在其他包引入橘忱。這似乎就是官方推薦的方式了赴魁。
package conf
import (
_ "embed"
)
//go:embed rabc_modal.conf
var CasbinModalStr string
//go:embed policy.csv
var PolicyCSV string
//go:embed config.yaml
var DefaultConfig string
另外我還在issue里看到,希望把/
作為模塊根目錄钝诚,這樣確實能解決這個問題颖御,但是這個被官方拒絕了。 https://github.com/golang/go/issues/58525