在實際開發中,經常會遇到各種不同的配置檔案。通常,程式執行的各種配置從外部讀取,以增強應用配置的靈活性。java 生態中的 springboot 提供了這種設計的典範。springboot 的應用程式,預設透過 application.yml 載入配置。預設的 application.yml 檔案打進 jar 包,如果想改變程式的行為,可以在jar 包的同級目錄下建立 application.yml 檔案或者透過引數指定配置檔案位置。那麼在 rust 生態裡有沒有辦法把預設配置檔案打包到二進位制檔案呢。
我們可以透過 [rust-embed](
https://github.com/pyrossh/rust-embed) 第三方庫來實現這一效果。
在實際開發中的典型場景是: 不指定任何配置檔案時,使用預設配置檔案;當應用程式同級目錄下包含配置檔案時載入該配置檔案。
* 定義嵌入檔案的位置及獲取函式
src/resources/embed_resource.rs 中定義了嵌入檔案的位置及獲取函式
```rust use rust_embed::RustEmbed; #[derive(RustEmbed)]
#[folder = "src/embedfiles/"]
struct Asset; pub fn get_app_default() -> Option<rust_embed::EmbeddedFile> {
Asset::get("./app_default.yml")
}
```
宏定義了嵌入檔案的目錄 '#[folder = "src/embedfiles/"]',獲取檔案函式以該目錄為根。
* 使用嵌入檔案
```rust fn main() { if Path::new("./app.yml").exists() { let contents =
fs::read_to_string("./app.yml").expect("Read file error!"); println!("{}", contents); return;
} let app = get_app_default().unwrap(); let f = std::str::from_utf8(app.data.as_ref()).unwrap(); println!("{}", f);
}
```
按照優先順序,我們先檢查應用同級目錄下有沒有app.yml檔案,如果有就載入,否則載入預設配置檔案。我們先前定義的獲取嵌入檔案的函式會返回rust_embed::EmbeddedFile 的 struct。透過解析該 struct 的 data 成員,獲取檔案內容。
* 測試
為了避免干擾,我們把編譯好的應用 mv 到 /tmp 目錄
```shell
cargo build
mv target/debug/embed /tmp
```
先執行 embed ,可以看到,輸出的是預設配置檔案的內容;在應用程式同級目錄建立 app.yml 檔案,隨便填寫些內容,再執行 embed 則輸出的是 app.yml 檔案的內容。
[原始碼地址](
https://github.com/jiashiwen/wenpanrust/tree/main/embed)
以上示例在 macos 上編譯執行透過,我們們下期見
作者:賈世聞