如何避免 Rust 中的硬编码值

How to avoid hard-coded values in Rust

下面是一个Maven/Java目录结构。

- src
  - main
    - java
    - resources
  - test
    - java
    - resources

- target

此处,resources 文件夹存放与应用程序相关的配置文件和资源文件,以避免在源文件中对其内容进行硬编码。

如何使用 Cargo 在 Rust 中实现相同的功能?

Maven 不包括您来源中的所有内容。事实上,它包含二进制文件,但甚至不必在 .jar 中包含源代码。您可以将其配置为说明要包含的内容,默认情况下是 resources 目录中的所有内容。

货物包源代码。 所有内容 都将包含在包装箱中,但与您的 .gitignore 文件匹配的内容除外。您可以通过在 [package] 部分添加 include or exclude 条目,在 Cargo.toml 文件中对其进行微调。

要访问这些文件,有几个选项。

例如,如果您的项目如下所示:

- Cargo.toml
- src
   - main.rs
- resources
   - hello.txt

访问hello.txt主要有以下三种方式。

include!

使用 include! 宏,您可以像这样从 main.rs 访问 hello.txt

let hello: &str = include!("../resources/hello.txt");

请注意,宏将直接在源中包含文件,就像您复制并粘贴文件的内容一样。所以我给出的示例只有在文件内容包含 "" 引号时才有效。任何 Rust 源代码都可以放在那里,并且必须在编译时包含它。这可以很方便地包含复杂的 Rust 结构,而无需编写解析代码。请注意,该路径是相对于包含它的源 .rs 文件的。

include_bytes!include_str!

include_bytes! 宏从文件创建一个固定大小的 u8 数组,将在编译时包含。

let bytes = include_bytes!("../resources/hello.txt").
let hello: String = String::from_bytes_lossy(bytes).to_string();

这很方便将任意二进制数据合并到您的应用程序中,例如图像,而无需在 运行 时加载它。该数组具有 'static 生命周期,因此将在应用程序的整个生命周期内保留在内存中。

include_str! 宏的工作方式类似,但会产生一个字符串切片,同样具有 'static 生命周期。

在运行时间

要在 运行 时加载文件,您可以使用:

let hello = std::fs::read_to_string("resources/hello.txt").unwrap();

这里的路径是相对于你的包的根目录的。这假设您从构建应用程序的地方 运行 使用 cargo run 连接应用程序。如果您正在部署二进制文件,您可能必须提供应用程序应在何处找到其资源的路径。

通常,这是首选方法。它更加灵活,因为您可以在 运行 时间交换配置或使用应用程序参数从不同位置加载。有很多用于解析不同文件格式的 crate,包括 json, toml 和许多其他格式。您可以控制您加载的数据的生命周期,因此您可以确保它在您完成后被释放。