Go打包附件內容到執行文件

前言

如果我們的應用在啓動的時候需要對數據庫進行初始化(比如建表等), 可以通過讀取.sql文件內容直接執行. 但是, 這樣會帶出一個問題:

  • 在發送可執行文件的時候, 需要連帶着附件文件, 並且相對路徑還不能出錯. 這樣太麻煩了
  • 有時我們並不希望附件的內容被使用者看到

處於種種原因, 我們不希望這部分額外的內容以附件的形式出現, 有沒有什麼辦法能夠將附件內容直接打包進可執行文件中呢?

打包方法

直接在文件中定義

最容易想到的, 就是直接在.go文件中定義字符串, 比如這樣:

var text = `xxx`

如此處理必然是可以的, 但有些不方便.

  1. .sql文件可能是通過mysqldump導出的, 每次導出之後還需要將內容複製到.go文件中
  2. 在編輯.sql文件的時候, IDE會提供語法高亮及輸入提示, 這些在字符串中都是沒有的

通過工具轉換

既然我們想要將內容直接放在文件中, 同時又想將內容打包到二進制中. 是否可以通過腳本處理呢? 腳本從附件中讀取內容, 並寫入到.go文件中.

有一個名爲go-bindata 的工具, 做的就是這樣的事情. 具體操作可自行搜索, 這裏不做贅述.

但是這個工具在3年前就不再更新了, 爲什麼呢? 因爲官方支持了.

go build

或許是因爲這樣的呼聲太大, 在go 1.16版本開始, 官方增加了embed包對這種操作進行了支持, 可以在編譯階段直接將靜態資源打包到二進制中.

其大致用法如下:

import "embed"

// 將內容直接打包到二進制文件中
//go:embed test.txt
var test string

//go:embed test.txt
var test1 []byte

// 同時打包多個文件. 後接文件名或目錄
//go:embed test.txt dir
// 作爲文件
var test2 embed.FS

func main() {
	// 輸出文件內容
	println(test)
	println(string(test1))
	
	b, err := test2.ReadFile("test.txt")
	if err != nil {
		panic(err)
	}
	println(string(b))
}

其中string/[]byte用來打包單個文件, embed.FS可以打包一批文件. 使用也比較簡單, 看下文檔就行了.

至此, Go程序已經可以天然且方便的將資源文件進行打包了.

總結

OK, 現在已經完美解決了我們最開始的問題, 以後在項目中遇到類似的需求, 可以直接使用啦.

至於其他語言, 比如PHP/Python等, 本來就是一堆源文件, 不會打包成二進制, 應該也不會有這種需求吧.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章