Go 語言打包靜態檔案
對於 Go 語言開發人員來說,在享受語言便利性的同時,最終編譯的單一可執行檔也是我們所熱衷的。但是,一旦遇到我們需要分發的東西不只有可執行檔的時候,事情就變得稍微有點複雜了,例如,需要分發個預設的設定檔;或者說是一個 Web 服務需要附帶一些簡單的 js/css 檔案之類的。
當然,對於經驗豐富的老司機們來說這都不是問題,例如 RH 系列的 RPM 是很多老司機們的選擇,像我這樣的新手也是覺得老司機們的這車開得好,可以很方便得管理一個分發包。但是,對於我們說的如果只有一點點檔案,我就來打個 rpm 包,似乎有點脫褲放屁的感覺;同時,有時我們可能是在 OSX/Win 平台跑,這又缺乏一定的通用性。
基於很多考慮,有同學就覺得為啥不把這些簡單的靜態檔案打包進可執行檔中,這樣我還是只分發一個檔案就可以了,其實我也挺喜歡這種方式的,好處就是很簡單,帶來的缺點當然也很明顯,自然分發可執行檔就大了。Anyway,有得有失,不妨一起和我看一下這種方式是如何?的。
go-bindata 介紹
在 Go 語言的 Awesome 中你可以看到很多靜態打包庫,但是,你卻看不到 go-bindata,哈哈,這很奇怪哈。而且相比於 Awesome 中列舉的這些庫,go-bindata 明顯更受歡迎,更流行。
go-bindata 很簡單,設計理念也不難理解。它的任務就是講靜態檔案封裝在一個 Go 語言的 Source Code 裡面,然後提供一個統一的介面,你通過這個介面傳入檔案路徑,它將給你返回對應路徑的檔案資料。這也就是說它不在乎你的檔案是字元型的檔案還是位元組型的,你自己處理,它只管封裝。
瞎說無憑,這裡就給出一個例子用於展示 go-bindata 的實際使用:

這裡可以看到,Line 1 就是一個使用 go-bindata 的例子,這裡講 etc/config.json
通過 go-bindata 封裝起來,然後下面就直接使用它,這樣在啟動並執行時候我就不用關注靜態檔案的具體位置了,我只認準 etc/config.json
就好了。
go-bindata 使用
首先,先介紹一下我的目錄結構,因為這對於待會介紹 go-bindata 的使用有很大關係:

在根目錄下我是定義了介面檔案的,然後再 etc
目錄下是放置我的設定檔:config.json
,這也是我希望打包的設定檔,然後再 file/service.go
裡面我是實現了需要進行檔案讀取的代碼。
1. 使用 go-bindata 打包靜態檔案
前面說了,go-bindata 是將靜態檔案打包成 go 檔案,所以第一步就是使用 go-bindata 讀取設定檔,然後再產生 go 檔案,具體的使用命令為:
$ go-bindata -pkg etc -o etc/bindata.go etc/
關於 go-bindata 的參數,可以使用 go-bindata --help
查看。使用上面這條命令之後,會發現在 etc
目錄下多了一個 bindata.go
檔案,下一步我們就會使用它來代替 etc/config.json
檔案。
使用靜態檔案
使用靜態檔案的代碼也是很簡單,我們只需要記住我們剛才產生 go 檔案的相對路徑,然後使用:
Asset("etc/config.json")
這樣的語句就可以讀取到靜態檔案了,整個 service 的範例程式碼為:

這裡的 Line 5 就是使用剛才我們產生的 bindata.go
來讀取靜態檔案的一段代碼。
總結
這篇文章很簡單得介紹了一下如何使用 go-bindata 來打包靜態檔案,同時在項目中如何使用這些靜態檔案。從這篇文章的介紹中應該可以看出 go-bindata 還是比較簡單的,沒有太複雜的方式,使用 go-bindata --help
也會發現參數還是相對比較少的,所以適合一些要求不複雜的情境。但是,這就意味著它的功能可能也是有限的,例如,預設是不支援 http.FileSystem
的,只能找其他外掛程式支援。