跃迁引擎

空気を読んだ雨降らないでよ

iOS Research & Development


Rust 工程结构初探

  1. Rust 项目的依赖管理机制

Rust 的依赖管理是基于项目的根 Cargo.toml 文件,而不是子目录中的 Cargo.toml 文件。如果再子目录的 Cargo.toml 文件中描述,即使同样在子目录中的.rs文件,也会出现识别不到的问题。

我们需要明确 Rust 项目的依赖管理机制。在 Rust 中,依赖管理是基于项目的根 Cargo.toml 文件进行的,而不是子目录中的 Cargo.toml 文件。这意味着子目录中的 Cargo.toml 文件不会被 Cargo 自动识别和使用。不过,你可以通过一些方法来组织和管理子目录中的依赖和模块。

  1. 为什么子目录中的 Cargo.toml 文件没有用?

  2. 依赖管理

    1. **Cargo.toml**:Cargo 会解析根 Cargo.toml 文件中的依赖,并将其下载和编译。
    2. 子目录 **Cargo.toml**:Cargo 不会自动解析子目录中的 Cargo.toml 文件,因此这些依赖不会被识别和使用。
  3. 模块系统

    1. Rust 的模块系统是基于文件和目录结构的,但依赖管理是集中式的,依赖项需要在根 Cargo.toml 中声明。
  4. 如何在子目录中组织依赖和模块

虽然子目录中的 Cargo.toml 文件不会被自动使用,但你可以通过以下方法来组织和管理子目录中的依赖和模块:

  1. 在根 Cargo.toml 中声明所有依赖

将所有依赖项添加到项目的根 Cargo.toml 文件中。这样,Cargo 会统一管理这些依赖。

Cargo.toml 文件路径

1
iris_net/Cargo.toml

Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "iris_net"
version = "0.1.0"
edition = "2021"

[dependencies]
# 网络库
reqwest = { version = "0.12", features = ["json"] }
# 网络缓存库,实现接口缓存
reqwest-cache = { version = "0.1.3" }
# 异步运行时库,提供了事件循环、任务调度、I/O 操作(如网络和文件操作)等功能
tokio = { version = "1", features = ["full"] }
# 序列化和反序列化库
serde = { version = "1.0.217", features = ["derive"] }
# 懒加载库,用于在编译时声明静态变量
lazy_static = "1.5.0"
  1. 在子目录中组织模块

在子目录中使用 mod.rs 文件来声明模块,并在根 Cargo.toml 中声明子目录为库或二进制文件。

项目结构

1
2
3
4
5
6
7
8
iris_net/
├── Cargo.toml
├── src/
│ ├── main.rs
│ └── net_core/
│ ├── mod.rs
│ ├── iris_environment.rs
│ └── iris_target.rs

Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "iris_net"
version = "0.1.0"
edition = "2021"

[dependencies]
# 网络库
reqwest = { version = "0.12", features = ["json"] }
# 网络缓存库,实现接口缓存
reqwest-cache = { version = "0.1.3" }
# 异步运行时库,提供了事件循环、任务调度、I/O 操作(如网络和文件操作)等功能
tokio = { version = "1", features = ["full"] }
# 序列化和反序列化库
serde = { version = "1.0.217", features = ["derive"] }
# 懒加载库,用于在编译时声明静态变量
lazy_static = "1.5.0"

iris_net/src/main.rs 文件内容

1
2
3
4
5
6
7
8
9
// src/main.rs
mod net_core;
fn main() {
// 设置环境变量
net_core::iris_environment::set_environment("release");
let target = net_core::iris_target::MyTarget::new("/api/data".to_string());
println!("Base URL: {}", target.base_url());
println!("Path: {}", target.path());
}

iris_net/src/net_core/mod.rs 文件内容

1
2
3
// src/net_core/mod.rs
pub mod iris_environment;
pub mod iris_target;

iris_net/src/net_core/iris_environment.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/net_core/iris_environment.rs
use lazy_static::lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref ENVIRONMENT: Mutex<String> = Mutex::new("test".to_string()); // 默认为测试环境
}
/// 设置环境变量
pub fn set_environment(env: &str) {
let mut environment = ENVIRONMENT.lock().unwrap();
*environment = env.to_string();
}
/// 获取环境变量
pub fn get_base_url_from_env() -> &'static str {
let environment = ENVIRONMENT.lock().unwrap();
match environment.as_str() {
"release" => "<https://release.example.com>",
"stage" => "<https://stage.example.com>",
_ => "<https://test.example.com>", // 默认为测试环境
}
}

iris_net/src/net_core/iris_target.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// src/net_core/iris_target.rs
use std::fmt::Debug;
use reqwest::header::HeaderMap;
use std::time::Duration;
use std::collections::HashMap;
use reqwest::Method;
use crate::net_core::iris_environment::{get_base_url_from_env, set_environment};
/// 请求目标(Target)接口
///
/// - Note: 所有具体的请求目标都将实现这个 trait。
pub trait IrisTarget: Debug {
type Response;
/// 请求目标基础 URL
fn base_url(&self) -> &str {
get_base_url_from_env()
}
/// 请求目标路径
fn path(&self) -> &str;
/// 请求目标方法
fn method(&self) -> Method {
Method::GET // 默认为 GET 请求
}
/// 请求目标参数(用于 GET 请求的查询参数)
fn parameters(&self) -> Option<HashMap<String, String>> {
None // 默认为空
}
/// 请求目标主体(用于 POST、PUT、PATCH 等请求的方法)
fn body(&self) -> Option<String> {
None // 默认为空
}
/// 请求目标请求头
fn headers(&self) -> Option<HeaderMap> {
None // 默认为空
}
/// 请求目标缓存过期时间
fn cache_expiration(&self) -> Option<Duration> {
Some(Duration::from_secs(60 * 60 * 24 * 7)) // 默认为 7 天
}
}
// 示例实现
pub struct MyTarget {
path: String,
}
impl MyTarget {
pub fn new(path: String) -> Self {
MyTarget { path }
}
}
impl IrisTarget for MyTarget {
type Response = String; // 替换为实际响应类型
fn path(&self) -> &str {
&self.path
}
}
  1. 验证

确保你已经正确添加了所有依赖,并且在 iris_environment.rsiris_target.rs 文件中正确引入了 lazy_static。然后运行你的项目:

1
2
3
cargo clean
cargo build
cargo run

如果一切配置正确,你应该能够看到输出:

1
2
Base URL: <https://release.example.com>
Path: /api/data
  1. 总结

  • 依赖声明位置:所有依赖项应该在项目的根 Cargo.toml 文件中声明。
  • 模块路径:使用 mod.rs 文件来声明子模块,并在需要的地方正确引入模块。
  • 重新构建项目:运行 cargo cleancargo build 以确保所有依赖都被正确下载和编译。

通过这些步骤,你应该能够解决 unresolved importuse of undeclared crate or module 的错误,并成功使用 lazy_static 来管理环境变量。

  1. 我是否可以理解为,子目录下的Cargo.toml完全是多余无用的?

这个理解部分是正确的,但有一些细微的差别。让我们详细解释一下子目录中的 Cargo.toml 文件的作用和限制。

  1. 子目录中的 Cargo.toml 文件的作用

  2. 独立的库或二进制项目

    1. 如果你希望 net_core 目录成为一个独立的库或二进制项目,你可以为其创建一个独立的 Cargo.toml 文件。这样,net_core 可以作为一个单独的 crate 进行开发、测试和发布。
  3. 依赖管理

    1. 在独立的 Cargo.toml 文件中,你可以声明该 crate 所需的依赖。这些依赖仅适用于该 crate,不会影响根项目或其他子 crate。
  4. 工作空间(Workspace)

    1. 如果你使用 Cargo 工作空间(workspace),可以在根 Cargo.toml 中声明多个成员(members),每个成员可以有自己的 Cargo.toml 文件。这样,每个成员都可以有自己的依赖和配置。
  5. 子目录中的 Cargo.toml 文件的限制

  6. 依赖解析

    1. 如果 net_core 目录不是一个独立的 crate,而是根项目的一部分,那么其 Cargo.toml 文件中的依赖不会被根项目自动识别和使用。根项目只会解析根 Cargo.toml 文件中的依赖。
  7. 模块系统

    1. Rust 的模块系统是基于文件和目录结构的,但依赖管理是集中式的。依赖项需要在根 Cargo.toml 中声明,以便在整个项目中统一管理。
  8. 如何正确组织项目

  9. Cargo.toml 中声明所有依赖

如果你希望 net_core 目录作为根项目的一部分,而不是独立的 crate,应该将所有依赖项添加到根 Cargo.toml 文件中。

Cargo.toml 文件路径

1
iris_net/Cargo.toml

Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "iris_net"
version = "0.1.0"
edition = "2021"

[dependencies]
# 网络库
reqwest = { version = "0.12", features = ["json"] }
# 网络缓存库,实现接口缓存
reqwest-cache = { version = "0.1.3" }
# 异步运行时库,提供了事件循环、任务调度、I/O 操作(如网络和文件操作)等功能
tokio = { version = "1", features = ["full"] }
# 序列化和反序列化库
serde = { version = "1.0.217", features = ["derive"] }
# 懒加载库,用于在编译时声明静态变量
lazy_static = "1.5.0"
  1. 在子目录中组织模块

在子目录中使用 mod.rs 文件来声明模块,并在根 Cargo.toml 中声明子目录为库或二进制文件。

项目结构

1
2
3
4
5
6
7
8
iris_net/
├── Cargo.toml
├── src/
│ ├── main.rs
│ └── net_core/
│ ├── mod.rs
│ ├── iris_environment.rs
│ └── iris_target.rs

Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "iris_net"
version = "0.1.0"
edition = "2021"

[dependencies]
# 网络库
reqwest = { version = "0.12", features = ["json"] }
# 网络缓存库,实现接口缓存
reqwest-cache = { version = "0.1.3" }
# 异步运行时库,提供了事件循环、任务调度、I/O 操作(如网络和文件操作)等功能
tokio = { version = "1", features = ["full"] }
# 序列化和反序列化库
serde = { version = "1.0.217", features = ["derive"] }
# 懒加载库,用于在编译时声明静态变量
lazy_static = "1.5.0"

iris_net/src/main.rs 文件内容

1
2
3
4
5
6
7
8
9
// src/main.rs
mod net_core;
fn main() {
// 设置环境变量
net_core::iris_environment::set_environment("release");
let target = net_core::iris_target::MyTarget::new("/api/data".to_string());
println!("Base URL: {}", target.base_url());
println!("Path: {}", target.path());
}

iris_net/src/net_core/mod.rs 文件内容

1
2
3
// src/net_core/mod.rs
pub mod iris_environment;
pub mod iris_target;

iris_net/src/net_core/iris_environment.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/net_core/iris_environment.rs
use lazy_static::lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref ENVIRONMENT: Mutex<String> = Mutex::new("test".to_string()); // 默认为测试环境
}
/// 设置环境变量
pub fn set_environment(env: &str) {
let mut environment = ENVIRONMENT.lock().unwrap();
*environment = env.to_string();
}
/// 获取环境变量
pub fn get_base_url_from_env() -> &'static str {
let environment = ENVIRONMENT.lock().unwrap();
match environment.as_str() {
"release" => "<https://release.example.com>",
"stage" => "<https://stage.example.com>",
_ => "<https://test.example.com>", // 默认为测试环境
}
}

iris_net/src/net_core/iris_target.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// src/net_core/iris_target.rs
use std::fmt::Debug;
use reqwest::header::HeaderMap;
use std::time::Duration;
use std::collections::HashMap;
use reqwest::Method;
use crate::net_core::iris_environment::{get_base_url_from_env, set_environment};
/// 请求目标(Target)接口
///
/// - Note: 所有具体的请求目标都将实现这个 trait。
pub trait IrisTarget: Debug {
type Response;
/// 请求目标基础 URL
fn base_url(&self) -> &str {
get_base_url_from_env()
}
/// 请求目标路径
fn path(&self) -> &str;
/// 请求目标方法
fn method(&self) -> Method {
Method::GET // 默认为 GET 请求
}
/// 请求目标参数(用于 GET 请求的查询参数)
fn parameters(&self) -> Option<HashMap<String, String>> {
None // 默认为空
}
/// 请求目标主体(用于 POST、PUT、PATCH 等请求的方法)
fn body(&self) -> Option<String> {
None // 默认为空
}
/// 请求目标请求头
fn headers(&self) -> Option<HeaderMap> {
None // 默认为空
}
/// 请求目标缓存过期时间
fn cache_expiration(&self) -> Option<Duration> {
Some(Duration::from_secs(60 * 60 * 24 * 7)) // 默认为 7 天
}
}
// 示例实现
pub struct MyTarget {
path: String,
}
impl MyTarget {
pub fn new(path: String) -> Self {
MyTarget { path }
}
}
impl IrisTarget for MyTarget {
type Response = String; // 替换为实际响应类型
fn path(&self) -> &str {
&self.path
}
}
  1. 使用子目录作为独立的 crate

如果你希望 net_core 目录成为一个独立的 crate,可以将其作为工作空间的一部分。以下是具体步骤:

  1. 创建工作空间

在项目根目录下创建一个 Cargo.toml 文件来定义工作空间。

Cargo.toml 文件路径

1
iris_net/Cargo.toml

Cargo.toml 文件内容

1
2
3
4
[workspace]
members = [
"net_core",
]
  1. 创建 net_coreCargo.toml

net_core 目录下创建一个 Cargo.toml 文件来声明 net_core crate 的依赖。

iris_net/net_core/Cargo.toml 文件路径

1
iris_net/net_core/Cargo.toml

iris_net/net_core/Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[package]
name = "net_core"
version = "0.1.0"
edition = "2021"

[dependencies]
# 网络库
reqwest = { version = "0.12", features = ["json"] }
# 网络缓存库,实现接口缓存
reqwest-cache = { version = "0.1.3" }
# 异步运行时库,提供了事件循环、任务调度、I/O 操作(如网络和文件操作)等功能
tokio = { version = "1", features = ["full"] }
# 序列化和反序列化库
serde = { version = "1.0.217", features = ["derive"] }
# 懒加载库,用于在编译时声明静态变量
lazy_static = "1.5.0"
  1. 组织模块

net_core 目录中使用 mod.rs 文件来声明模块。

项目结构

1
2
3
4
5
6
7
8
iris_net/
├── Cargo.toml
└── net_core/
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── iris_environment.rs
│ └── iris_target.rs

iris_net/net_core/src/lib.rs 文件内容

1
2
3
// src/lib.rs
pub mod iris_environment;
pub mod iris_target;

iris_net/net_core/src/iris_environment.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/iris_environment.rs
use lazy_static::lazy_static;
use std::sync::Mutex;
lazy_static! {
static ref ENVIRONMENT: Mutex<String> = Mutex::new("test".to_string()); // 默认为测试环境
}
/// 设置环境变量
pub fn set_environment(env: &str) {
let mut environment = ENVIRONMENT.lock().unwrap();
*environment = env.to_string();
}
/// 获取环境变量
pub fn get_base_url_from_env() -> &'static str {
let environment = ENVIRONMENT.lock().unwrap();
match environment.as_str() {
"release" => "<https://release.example.com>",
"stage" => "<https://stage.example.com>",
_ => "<https://test.example.com>", // 默认为测试环境
}
}

iris_net/net_core/src/iris_target.rs 文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// src/iris_target.rs
use std::fmt::Debug;
use reqwest::header::HeaderMap;
use std::time::Duration;
use std::collections::HashMap;
use reqwest::Method;
use crate::iris_environment::{get_base_url_from_env, set_environment};
/// 请求目标(Target)接口
///
/// - Note: 所有具体的请求目标都将实现这个 trait。
pub trait IrisTarget: Debug {
type Response;
/// 请求目标基础 URL
fn base_url(&self) -> &str {
get_base_url_from_env()
}
/// 请求目标路径
fn path(&self) -> &str;
/// 请求目标方法
fn method(&self) -> Method {
Method::GET // 默认为 GET 请求
}
/// 请求目标参数(用于 GET 请求的查询参数)
fn parameters(&self) -> Option<HashMap<String, String>> {
None // 默认为空
}
/// 请求目标主体(用于 POST、PUT、PATCH 等请求的方法)
fn body(&self) -> Option<String> {
None // 默认为空
}
/// 请求目标请求头
fn headers(&self) -> Option<HeaderMap> {
None // 默认为空
}
/// 请求目标缓存过期时间
fn cache_expiration(&self) -> Option<Duration> {
Some(Duration::from_secs(60 * 60 * 24 * 7)) // 默认为 7 天
}
}
// 示例实现
pub struct MyTarget {
path: String,
}
impl MyTarget {
pub fn new(path: String) -> Self {
MyTarget { path }
}
}
impl IrisTarget for MyTarget {
type Response = String; // 替换为实际响应类型
fn path(&self) -> &str {
&self.path
}
}
  1. 在根项目中使用 net_core crate

在根项目的 Cargo.toml 中添加 net_core 作为依赖。

Cargo.toml 文件路径

1
iris_net/Cargo.toml

Cargo.toml 文件内容

1
2
3
4
5
6
7
8
9
10
[workspace]
members = [
"net_core",
]
[package]
name = "iris_net"
version = "0.1.0"
edition = "2021"
[dependencies]
net_core = { path = "net_core" }

iris_net/src/main.rs 文件内容

1
2
3
4
5
6
7
8
9
// src/main.rs
use net_core::{set_environment, MyTarget, IrisTarget};
fn main() {
// 设置环境变量
set_environment("release");
let target = MyTarget::new("/api/data".to_string());
println!("Base URL: {}", target.base_url());
println!("Path: {}", target.path());
}
  1. 总结

  • Cargo.toml 中声明所有依赖
    • 如果 net_core 目录作为根项目的一部分,所有依赖项应该在根 Cargo.toml 文件中声明。
  • 子目录中的 Cargo.toml 文件
    • 如果 net_core 目录是一个独立的 crate,可以在其 Cargo.toml 文件中声明依赖。
    • 如果 net_core 目录作为根项目的一部分,子目录中的 Cargo.toml 文件不会被自动识别和使用。
  • 工作空间
    • 可以通过 Cargo 工作空间将 net_core 目录作为一个独立的 crate 进行管理。
  1. 示例项目结构

  2. 根项目结构(作为独立 crate)
1
2
3
4
5
6
7
8
iris_net/
├── Cargo.toml
└── src/
├── main.rs
└── net_core/
├── mod.rs
├── iris_environment.rs
└── iris_target.rs
  1. 根项目结构(作为工作空间)
1
2
3
4
5
6
7
8
iris_net/
├── Cargo.toml
└── net_core/
├── Cargo.toml
└── src/
├── lib.rs
├── iris_environment.rs
└── iris_target.rs

通过这些步骤,你可以正确组织和管理项目的依赖和模块,确保 lazy_static 和其他依赖项能够被正确识别和使用。

  1. 模块(mod)和库(lib)

  2. Rust 中模块和库的关系

在 Rust 中,模块 是两个不同的概念,但它们之间有紧密的联系。理解它们之间的关系有助于更好地组织和管理代码。

  1. 模块 (Module)

  • 定义:模块是 Rust 中用于组织代码的基本单元。模块可以包含函数、结构体、枚举、常量等,并且可以通过 pub 关键字控制其可见性。
  • 作用:模块用于将代码逻辑分隔成多个部分,提高代码的可读性和维护性。模块还可以通过嵌套形成层次结构。
  • 声明方式
    • 在文件中使用 mod 关键字声明模块。
    • 模块可以是单个 .rs 文件,也可以是一个包含 mod.rs 的目录。
1
2
3
// src/iris_net/mod.rs
pub mod inmethod;
pub mod intarget;
  1. 库 (Library)

  • 定义:库是编译后生成的二进制文件(如 .rlib.so),可以在其他项目或程序中引用和使用。库通常提供一组功能,供外部代码调用。
  • 作用:库用于封装和复用代码,使得不同项目可以共享相同的代码逻辑。Rust 项目可以通过 Cargo.toml 文件指定依赖库。
  • 类型
    • **库包 (Library crate)**:生成静态库或动态库,供其他项目使用。
    • **二进制包 (Binary crate)**:生成可执行文件,通常是应用程序的入口点。
  1. 模块与库的关系

  • 库由模块组成:一个库是由多个模块组成的。库中的所有功能都是通过模块来实现和组织的。库的根模块通常是 lib.rsmain.rs
1
2
// src/lib.rs (库的根模块)
pub mod iris_net;
  • 模块可以跨库重用:模块不仅可以存在于同一个库内,还可以被其他库或二进制包引用。通过 Cargo.toml 文件中的依赖项声明,可以在不同项目中重用模块。
1
2
3
# Cargo.toml
[dependencies]
some_library = "0.1.0"
  • 库的可见性控制:库中哪些模块和功能对外部可用,取决于 pub 关键字的使用。只有标记为 pub 的模块、函数、结构体等才能被外部代码访问。
  1. 示例

假设你有一个名为 iris_net 的库,它包含多个模块:

1
2
3
4
5
// src/lib.rs (库的根模块)
pub mod iris_net;
// src/iris_net/mod.rs (iris_net 模块)
pub mod inmethod;
pub mod intarget;

文件结构:

1
2
3
4
5
6
src/
├── lib.rs
└── iris_net/
├── mod.rs
├── inmethod.rs
└── intarget.rs

在这个例子中:

  • lib.rs 是库的根模块,它声明了 iris_net 模块。
  • iris_net 模块进一步包含了 inmethodintarget 子模块。
  1. 总结

  • 模块 是 Rust 中用于组织代码的基本单元,提供了代码的分隔和可见性控制。
  • 是由多个模块组成的编译产物,可以在其他项目中引用和使用。
  • 模块与库的关系 是:库由模块组成,模块可以跨库重用,库的可见性由 pub 关键字控制。

通过合理使用模块和库,你可以构建出结构清晰、易于维护且高度复用的 Rust 项目。

  1. Rust 中库的命名规则

在 Rust 中,库的命名规则主要遵循以下几个方面,以确保代码的一致性和可读性。这些规则不仅适用于库本身,还适用于库中的模块、函数、结构体等。

  1. 库名命名规范

  • **蛇形命名法 (snake_case)**:库名应使用小写字母,并用下划线分隔单词。例如,iris_net 是符合规范的,而 IrisNetirisNet 则不符合。
1
2
3
# Cargo.toml
[package]
name = "iris_net"
  • 简洁明了:库名应尽量简洁且具有描述性,避免过于冗长或模糊不清的名字。
  1. 库包与二进制包的区别

  • **库包 (Library crate)**:通常用于提供可重用的功能,供其他项目依赖。库包的根文件通常是 lib.rs
  • **二进制包 (Binary crate)**:用于生成可执行文件,通常是应用程序的入口点。二进制包的根文件通常是 main.rs

对于库包,库名应该清晰地反映其功能和用途,以便其他开发者能够快速理解其作用。

  1. 命名冲突与唯一性

  • 避免命名冲突:为了防止与其他库发生命名冲突,建议选择独特且具体的库名。可以考虑加入项目或组织的名称作为前缀。
1
2
3
# Cargo.toml
[package]
name = "my_org_iris_net"
  • 使用版本控制:通过 Cargo.toml 文件中的 version 字段管理库的版本,确保不同版本之间的兼容性和更新。
  1. 命名示例

以下是一些符合命名规范的库名示例:

1
2
3
4
5
6
# Cargo.toml
[package]
name = "http_client" # 简洁明了,描述 HTTP 客户端功能
name = "json_parser" # 描述 JSON 解析器功能
name = "image_processor" # 描述图像处理功能
name = "my_org_network_lib" # 包含组织名称,避免冲突
  1. 其他注意事项

  • 一致性:在整个项目中保持命名的一致性。如果库中有多个模块,模块名也应遵循相同的命名规范。
  • 文档化:为库编写详细的文档,解释其功能和使用方法,帮助其他开发者更好地理解和使用该库。
  1. 总结

Rust 中库的命名规则主要包括:

  • 使用 **蛇形命名法 (snake_case)**。
  • 保持 简洁明了 的名字。
  • 避免 命名冲突,必要时加入组织或项目名称。
  • 使用 版本控制 管理库的不同版本。

遵循这些规则可以帮助你创建清晰、易用且易于维护的 Rust 库。通过合理的命名,不仅可以提高代码的可读性,还能减少潜在的错误和冲突。

  1. 在lib.rs中,应当写什么内容

在 Rust 中,lib.rs 文件是库包(Library crate)的根文件,它定义了库的公共接口和结构。以下是 lib.rs 文件中应该包含的内容和最佳实践:

  1. 模块声明

lib.rs 文件通常用于声明和组织库中的各个模块。你可以使用 mod 关键字来声明模块,并通过 pub 关键字将模块公开给外部使用。

1
2
3
// src/lib.rs
pub mod iris_net;
pub mod utils;
  1. 公共接口

lib.rs 文件应该定义库的公共接口,即外部代码可以访问的函数、结构体、枚举等。这些公共项通常使用 pub 关键字声明。

1
2
3
4
5
// src/lib.rs
pub mod iris_net;
pub mod utils;
pub use iris_net::IrisNet;
pub use utils::HelperFunction;
  1. 依赖管理

虽然依赖管理主要在 Cargo.toml 文件中进行,但在 lib.rs 文件中,你可能会使用这些依赖项来实现库的功能。

1
2
3
4
5
6
// src/lib.rs
extern crate some_dependency;
pub mod iris_net;
pub mod utils;
pub use iris_net::IrisNet;
pub use utils::HelperFunction;
  1. 文档注释

为库中的公共项添加文档注释,以便其他开发者能够理解如何使用这些功能。文档注释使用 /// 开头。

1
2
3
4
5
6
7
8
9
// src/lib.rs
/// 这是 iris_net 模块,提供网络相关功能。
pub mod iris_net;
/// 这是 utils 模块,提供一些实用工具函数。
pub mod utils;
/// 这是 IrisNet 结构体,用于网络通信。
pub use iris_net::IrisNet;
/// 这是 HelperFunction 函数,提供一些辅助功能。
pub use utils::HelperFunction;
  1. 示例代码

以下是一个完整的 lib.rs 文件示例,展示了如何组织模块、定义公共接口和添加文档注释:

1
2
3
4
5
6
7
8
9
// src/lib.rs
/// 这是 iris_net 模块,提供网络相关功能。
pub mod iris_net;
/// 这是 utils 模块,提供一些实用工具函数。
pub mod utils;
/// 这是 IrisNet 结构体,用于网络通信。
pub use iris_net::IrisNet;
/// 这是 HelperFunction 函数,提供一些辅助功能。
pub use utils::HelperFunction;
  1. 其他注意事项

  • 模块组织:合理组织模块,确保代码结构清晰。
  • 可见性控制:使用 pub 关键字控制模块和项的可见性,避免不必要的暴露。
  • 文档编写:为库中的公共项编写详细的文档注释,提高库的可使用性。
  1. 总结

lib.rs 文件是库包的根文件,应该包含以下内容:

  • 模块声明:使用 mod 关键字声明模块。
  • 公共接口:使用 pub 关键字定义公共项。
  • 依赖管理:使用 extern crate 声明外部依赖(在现代 Rust 中通常不需要显式声明,use 语句会自动处理)。
  • 文档注释:为公共项添加文档注释,提高代码的可读性和可维护性。

通过合理组织 lib.rs 文件,你可以创建一个结构清晰、功能完善的 Rust 库。

  1. mod.rs中都可以写哪些内容

在 Rust 中,mod.rs 文件是模块的根文件,用于定义和组织模块的内容。mod.rs 文件可以包含多种内容,以帮助构建和管理模块的结构。以下是 mod.rs 文件中可以写的内容及其详细解释:

  1. 模块声明

  • 声明子模块:使用 mod 关键字声明子模块。
1
2
3
// src/iris_net/mods/mod.rs
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
  1. 重新导出(Re-export)

  • 重新导出项:使用 pub use 语法将子模块中的项重新导出到当前模块的公共接口中。
1
2
3
4
5
// src/iris_net/mods/mod.rs
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
pub use inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use intarget::INTarget; /// 导出 INTarget trait
  1. 结构体、枚举、函数等定义

  • 定义结构体
1
2
3
4
// src/iris_net/mods/mod.rs
pub struct MyStruct {
pub field: String,
}
  • 定义枚举
1
2
3
4
5
// src/iris_net/mods/mod.rs
pub enum MyEnum {
Variant1,
Variant2,
}
  • 定义函数
1
2
3
4
// src/iris_net/mods/mod.rs
pub fn my_function() {
println!("Hello from my_function!");
}
  1. 使用外部依赖

  • 使用外部 crate:通过 use 语句引入外部 crate 中的项。
1
2
3
4
5
6
// src/iris_net/mods/mod.rs
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct MySerializableStruct {
pub field: String,
}
  1. 实现 Trait

  • 实现 Trait:为结构体或枚举实现 trait。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/iris_net/mods/mod.rs
use std::fmt::Debug;
pub trait MyTrait {
fn my_method(&self);
}
pub struct MyStruct {
pub field: String,
}
impl MyTrait for MyStruct {
fn my_method(&self) {
println!("MyStruct field: {}", self.field);
}
}
impl Debug for MyStruct {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "MyStruct {{ field: {} }}", self.field)
}
}
  1. 文档注释

  • 添加文档注释:为模块、结构体、枚举、函数等添加文档注释,以便生成文档。
1
2
3
4
5
6
7
8
9
10
11
12
13
// src/iris_net/mods/mod.rs
/// 这是 mods 模块,包含请求方法执行器和请求目标接口。
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
/// 这是一个示例结构体。
pub struct MyStruct {
/// 这是一个字段。
pub field: String,
}
/// 这是一个示例函数。
pub fn my_function() {
println!("Hello from my_function!");
}
  1. 其他内容

  • 常量和静态变量
1
2
3
// src/iris_net/mods/mod.rs
pub const MY_CONSTANT: i32 = 42;
pub static MY_STATIC: &str = "Hello, world!";
  • 宏定义
1
2
3
4
5
6
// src/iris_net/mods/mod.rs
macro_rules! my_macro {
() => {
println!("Hello from my_macro!");
};
}
  1. 示例 mod.rs 文件

以下是一个完整的 mod.rs 文件示例,展示了上述各种内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// src/iris_net/mods/mod.rs
/// 这是 mods 模块,包含请求方法执行器和请求目标接口。
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
/// 这是一个示例结构体。
pub struct MyStruct {
/// 这是一个字段。
pub field: String,
}
/// 这是一个示例函数。
pub fn my_function() {
println!("Hello from my_function!");
}
/// 这是一个示例常量。
pub const MY_CONSTANT: i32 = 42;
/// 这是一个示例静态变量。
pub static MY_STATIC: &str = "Hello, world!";
/// 这是一个示例宏。
macro_rules! my_macro {
() => {
println!("Hello from my_macro!");
};
}
// 重新导出项
pub use inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use intarget::INTarget; /// 导出 INTarget trait
  1. 总结

mod.rs 文件可以包含以下内容:

  • 模块声明:使用 mod 关键字声明子模块。
  • 重新导出:使用 pub use 语法重新导出子模块中的项。
  • 结构体、枚举、函数等定义:定义和实现各种 Rust 项。
  • 使用外部依赖:通过 use 语句引入外部 crate 中的项。
  • 实现 Trait:为结构体或枚举实现 trait。
  • 文档注释:为模块、结构体、枚举、函数等添加文档注释。
  • 常量和静态变量:定义常量和静态变量。
  • 宏定义:定义宏。

通过合理组织 mod.rs 文件,你可以创建一个结构清晰、功能完善的 Rust 模块。

  1. extern crate 的作用

在 Rust 中,extern crate 用于声明外部依赖项。然而,在现代 Rust 版本(Rust 2018 及更高版本)中,extern crate 的使用已经不再是必需的,因为 use 语句会自动处理依赖项的引入。尽管如此,了解 extern crate 的作用仍然是有用的。

  1. extern crate 的基本作用

extern crate 用于告诉 Rust 编译器在编译时链接一个外部 crate(库)。这使得你可以在代码中使用该 crate 中定义的模块、函数、结构体等。

  1. 语法

1
extern crate some_dependency;
  • some_dependency:这是你想要引入的外部 crate 的名称。
  1. 示例

假设你有一个 Cargo.toml 文件,其中声明了一个依赖项 serde

1
2
3
# Cargo.toml
[dependencies]
serde = { version = "1.0", features = ["derive"] }

lib.rs 文件中,你可以使用 extern crate 来声明这个依赖项:

1
2
3
4
5
6
7
// src/lib.rs
extern crate serde;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyStruct {
field: String,
}
  1. 现代 Rust 中的自动处理

在 Rust 2018 及更高版本中,use 语句会自动处理依赖项的引入,因此 extern crate 可以省略。上述示例可以简化为:

1
2
3
4
5
6
// src/lib.rs
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyStruct {
field: String,
}
  1. 详细解释

  • 链接外部库extern crate 告诉编译器需要链接 some_dependency 这个外部库。
  • 命名空间管理:在某些情况下,extern crate 可以用于重命名依赖项,以便在代码中使用不同的名称引用它。
1
2
extern crate some_dependency as sd;
use sd::SomeStruct;
  • 版本控制extern crate 本身不处理版本控制,版本控制通常在 Cargo.toml 文件中通过 [dependencies] 部分进行管理。
  1. 总结

  • extern crate 的作用:声明并链接外部 crate。
  • 现代 Rust:在 Rust 2018 及更高版本中,use 语句会自动处理依赖项的引入,因此 extern crate 通常是不必要的。
  • 最佳实践:在现代 Rust 项目中,建议直接使用 use 语句来引入依赖项,除非有特殊需求(如重命名依赖项)。

具体到你的 lib.rs 文件

假设你的 lib.rs 文件如下:

1
2
3
4
// src/iris_net/lib.rs
extern crate some_dependency;
pub mod inmethod;
pub mod intarget;

你可以简化为:

1
2
3
// src/iris_net/lib.rs
pub mod inmethod;
pub mod intarget;

然后在需要使用 some_dependency 的模块中直接使用 use 语句:

1
2
3
4
5
6
// src/iris_net/inmethod.rs
use some_dependency::SomeStruct;
pub fn some_function() {
let instance = SomeStruct::new();
// 使用 instance 进行操作
}

这样可以保持代码的简洁和现代风格。

  1. pub use 的作用

在 Rust 中,pub use 用于重新导出(re-export)模块中的项,使其在当前模块的公共接口中可用。这有助于简化模块的使用,并提高代码的可读性和可维护性。以下是详细的解释:

  1. 基本语法

1
pub use some_module::SomeItem;
  • some_module:要导出项所在的模块。
  • SomeItem:要导出的具体项(如函数、结构体、枚举等)。
  • pub:使导出的项在当前模块的公共接口中可用。
  1. 示例

假设你有一个库结构如下:

1
2
3
4
5
src/
└── iris_net/
├── lib.rs
├── inmethod.rs
└── utils.rs

文件内容如下:

src/iris_net/lib.rs:

1
2
3
4
5
// src/iris_net/lib.rs
pub mod inmethod;
pub mod utils;
pub use inmethod::IrisNet;
pub use utils::HelperFunction;

src/iris_net/inmethod.rs:

1
2
3
4
5
6
7
8
9
// src/iris_net/inmethod.rs
pub struct IrisNet {
// 结构体定义
}
impl IrisNet {
pub fn new() -> Self {
IrisNet {}
}
}

src/iris_net/utils.rs:

1
2
3
4
// src/iris_net/utils.rs
pub fn HelperFunction() {
// 函数实现
}
  1. 详细解释

  • 重新导出项pub use inmethod::IrisNet;inmethod 模块中的 IrisNet 结构体重新导出到 iris_net 模块的公共接口中。
  • 简化使用:通过重新导出,外部代码可以直接从 iris_net 模块中使用 IrisNet,而不需要知道 IrisNet 实际上定义在 inmethod 模块中。
1
2
3
4
5
6
// 外部代码示例
use iris_net::IrisNet;
fn main() {
let net = IrisNet::new();
// 使用 net 进行操作
}
  • 提高可读性:重新导出可以使模块的公共接口更加清晰,外部代码不需要了解内部模块的结构,只需关注顶层模块的接口。
  1. 具体到你的 lib.rs 文件

在你的 lib.rs 文件中:

1
2
3
4
5
// src/iris_net/lib.rs
pub mod inmethod;
pub mod utils;
pub use iris_net::IrisNet;
pub use utils::HelperFunction;

这里有几点需要注意:

  1. 模块声明

    • pub mod inmethod;pub mod utils; 声明了 inmethodutils 模块,并使它们在 iris_net 模块中可用。
  2. 重新导出项

    • pub use inmethod::IrisNet; 试图将 inmethod 模块中的 IrisNet 结构体重新导出到 iris_net 模块的公共接口中。
    • pub use utils::HelperFunction;utils 模块中的 HelperFunction 函数重新导出到 iris_net 模块的公共接口中。
  3. 修正建议

lib.rs 文件中,pub use iris_net::IrisNet; 的写法是错误的,因为 IrisNet 实际上是在 inmethod 模块中定义的,而不是在 iris_net 模块中。正确的写法应该是:

1
2
3
4
5
// src/iris_net/lib.rs
pub mod inmethod;
pub mod utils;
pub use inmethod::IrisNet;
pub use utils::HelperFunction;

这样,外部代码可以直接从 iris_net 模块中使用 IrisNetHelperFunction

1
2
3
4
5
6
7
// 外部代码示例
use iris_net::{IrisNet, HelperFunction};
fn main() {
let net = IrisNet::new();
HelperFunction();
// 使用 net 和 HelperFunction 进行操作
}
  1. 总结

  • pub use 的作用:重新导出模块中的项,使其在当前模块的公共接口中可用。
  • 简化使用:外部代码可以直接使用重新导出的项,而不需要了解内部模块的结构。
  • 提高可读性:使模块的公共接口更加清晰和简洁。

通过合理使用 pub use,你可以创建一个结构清晰、易于使用的 Rust 库。

  1. 不同 mod 中同名方法冲突处理

  2. main.rs 中引用两个模块时,同名方法的冲突处理

在 Rust 中,如果两个模块中定义了同名的方法(例如 execute_request),直接引用这两个模块会导致命名冲突。为了避免这种冲突,可以使用以下几种方法:

  1. 使用模块路径

通过指定完整的模块路径来调用具体的方法,可以避免命名冲突。

1
2
3
4
5
6
7
// main.rs
mod A;
mod B;
fn main() {
A::execute_request();
B::execute_request();
}
  1. 使用 as 关键字重命名

可以使用 as 关键字为导入的方法或函数重命名,以避免冲突。

1
2
3
4
5
6
7
8
9
// main.rs
mod A;
mod B;
use A::execute_request as execute_request_a;
use B::execute_request as execute_request_b;
fn main() {
execute_request_a();
execute_request_b();
}
  1. 使用模块块

将每个模块的方法调用放在不同的模块块中,可以避免命名冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.rs
mod A;
mod B;
fn main() {
{
use A::execute_request;
execute_request();
}
{
use B::execute_request;
execute_request();
}
}
  1. 使用 selfsuper 关键字

在更复杂的模块结构中,可以使用 selfsuper 关键字来明确指定方法的来源。

1
2
3
4
5
6
7
// main.rs
mod A;
mod B;
fn main() {
A::execute_request();
B::execute_request();
}
  1. 示例代码

假设你有两个模块 AB,它们都有一个同名方法 execute_request

src/main.rs:

1
2
3
4
5
6
mod A;
mod B;
fn main() {
A::execute_request();
B::execute_request();
}

src/A.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from module A");
}

src/B.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from module B");
}
  1. 使用 as 关键字重命名的示例

src/main.rs:

1
2
3
4
5
6
7
8
mod A;
mod B;
use A::execute_request as execute_request_a;
use B::execute_request as execute_request_b;
fn main() {
execute_request_a();
execute_request_b();
}

src/A.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from module A");
}

src/B.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from module B");
}
  1. 总结
  • 使用模块路径:通过指定完整的模块路径来调用具体的方法。
  • 使用 as 关键字重命名:为导入的方法或函数重命名,以避免冲突。
  • 使用模块块:将每个模块的方法调用放在不同的模块块中。
  • 使用 self super 关键字:在复杂的模块结构中明确指定方法的来源。

通过这些方法,你可以有效地避免在 main.rs 中引用两个模块时出现的同名方法冲突问题。选择哪种方法取决于你的具体需求和代码结构。

Q&A

如果在 mod.rs 中写了如下内容,在 lib.rs 中应该如何写

假设你在 mod.rs 文件中写了以下内容:

src/iris_net/mods/mod.rs:

1
2
3
4
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
pub use inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use intarget::Target as INTarget; /// 导出 INTarget trait;

为了确保 lib.rs 文件能够正确地暴露这些模块和项,你需要在 lib.rs 中进行相应的调整。以下是详细的步骤和建议:

  1. 声明 mods 模块

首先,你需要在 lib.rs 中声明 mods 模块,以便能够访问 mods 模块中的内容。

src/iris_net/lib.rs:

1
pub mod mods;
  1. 重新导出 mods 模块中的内容

接下来,你需要在 lib.rs 中重新导出 mods 模块中的内容,以便外部代码可以直接访问这些模块和项。

src/iris_net/lib.rs:

1
2
3
pub mod mods;
pub use mods::inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use mods::intarget::Target as INTarget; /// 导出 INTarget trait
  1. 完整示例

以下是完整的 lib.rs 文件示例,展示了如何正确地声明和重新导出 mods 模块中的内容:

src/iris_net/lib.rs:

1
2
3
pub mod mods;
pub use mods::inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use mods::intarget::Target as INTarget; /// 导出 INTarget trait

src/iris_net/mods/mod.rs:

1
2
3
4
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
pub use inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use intarget::Target as INTarget; /// 导出 INTarget trait

src/iris_net/mods/inmethod.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from inmethod");
}

src/iris_net/mods/intarget.rs:

1
2
3
4
5
6
7
8
9
10
11
use std::fmt::Debug;
/// 请求目标(Target)接口
///
/// - Note: 所有具体的请求目标都将实现这个 trait。
pub trait Target: Debug {
fn base_url(&self) -> &str;
fn path(&self) -> &str;
fn method(&self) -> Method;
fn body(&self) -> Option<String>;
fn headers(&self) -> Option<HeaderMap>;
}
  1. 使用示例

假设你在 main.rs 中使用这些模块和项:

src/main.rs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
mod iris_net;
fn main() {
iris_net::in_execute_request();
let target: Box<dyn iris_net::INTarget> = Box::new(MyTarget {
base_url: "<http://example.com>".to_string(),
path: "/api".to_string(),
method: Method::GET,
body: None,
headers: None,
});
println!("Base URL: {}", target.base_url());
println!("Path: {}", target.path());
println!("Method: {:?}", target.method());
}
struct MyTarget {
base_url: String,
path: String,
method: Method,
body: Option<String>,
headers: Option<HeaderMap>,
}
impl Debug for MyTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MyTarget")
.field("base_url", &self.base_url)
.field("path", &self.path)
.field("method", &self.method)
.field("body", &self.body)
.field("headers", &self.headers)
.finish()
}
}
impl iris_net::INTarget for MyTarget {
fn base_url(&self) -> &str {
&self.base_url
}
fn path(&self) -> &str {
&self.path
}
fn method(&self) -> Method {
self.method
}
fn body(&self) -> Option<String> {
self.body.clone()
}
fn headers(&self) -> Option<HeaderMap> {
self.headers.clone()
}
}
use std::fmt::Debug;
use http::Method;
use http::header::HeaderMap;
  1. 总结
  • 声明模块:在 lib.rs 中声明 mods 模块。
  • 重新导出项:在 lib.rs 中重新导出 mods 模块中的内容,以便外部代码可以直接访问这些模块和项。

通过这种方式,你可以确保 lib.rs 文件正确地暴露 mods 模块中的内容,并且外部代码可以方便地使用这些模块和项。

如果这些内容直接写在 lib.rs 中,是否 mod.rs 中就不需要写内容了?

是的,如果这些内容直接写在 lib.rs 中,那么 mod.rs 文件就不需要写这些内容了。具体来说,lib.rs 文件作为库的根文件,可以完全包含模块声明和重新导出的逻辑。以下是详细的解释和示例:

  1. 直接在 lib.rs 中写内容

如果你决定将所有模块声明和重新导出的逻辑直接写在 lib.rs 文件中,那么 mod.rs 文件可以保持为空或删除。以下是具体的步骤和示例:

src/iris_net/lib.rs:

1
2
3
4
pub mod inmethod; /// 请求方法执行器
pub mod intarget; /// 请求目标(Target)接口
pub use inmethod::execute_request as in_execute_request; /// 导出 in_execute_request 方法
pub use intarget::Target as INTarget; /// 导出 INTarget trait

src/iris_net/inmethod.rs:

1
2
3
pub fn execute_request() {
println!("Executing request from inmethod");
}

src/iris_net/intarget.rs:

1
2
3
4
5
6
7
8
9
10
11
use std::fmt::Debug;
/// 请求目标(Target)接口
///
/// - Note: 所有具体的请求目标都将实现这个 trait。
pub trait Target: Debug {
fn base_url(&self) -> &str;
fn path(&self) -> &str;
fn method(&self) -> Method;
fn body(&self) -> Option<String>;
fn headers(&self) -> Option<HeaderMap>;
}
  1. 删除 mod.rs 文件

如果你不再需要 mod.rs 文件,可以将其删除。项目结构将简化为:

1
2
3
4
5
src/
└── iris_net/
├── lib.rs
├── inmethod.rs
└── intarget.rs
  1. 使用示例

假设你在 main.rs 中使用这些模块和项:

src/main.rs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
mod iris_net;
fn main() {
iris_net::in_execute_request();
let target: Box<dyn iris_net::INTarget> = Box::new(MyTarget {
base_url: "<http://example.com>".to_string(),
path: "/api".to_string(),
method: Method::GET,
body: None,
headers: None,
});
println!("Base URL: {}", target.base_url());
println!("Path: {}", target.path());
println!("Method: {:?}", target.method());
}
struct MyTarget {
base_url: String,
path: String,
method: Method,
body: Option<String>,
headers: Option<HeaderMap>,
}
impl Debug for MyTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MyTarget")
.field("base_url", &self.base_url)
.field("path", &self.path)
.field("method", &self.method)
.field("body", &self.body)
.field("headers", &self.headers)
.finish()
}
}
impl iris_net::INTarget for MyTarget {
fn base_url(&self) -> &str {
&self.base_url
}
fn path(&self) -> &str {
&self.path
}
fn method(&self) -> Method {
self.method
}
fn body(&self) -> Option<String> {
self.body.clone()
}
fn headers(&self) -> Option<HeaderMap> {
self.headers.clone()
}
}
use std::fmt::Debug;
use http::Method;
use http::header::HeaderMap;
  1. 总结
  • 直接在 lib.rs 中写内容:如果将所有模块声明和重新导出的逻辑直接写在 lib.rs 文件中,那么 mod.rs 文件可以保持为空或删除。
  • 项目结构简化:删除 mod.rs 文件后,项目结构更加简洁。
  • 保持一致性:确保所有模块声明和重新导出的逻辑在 lib.rs 文件中统一管理。

通过这种方式,你可以简化项目结构,并确保 lib.rs 文件正确地暴露所有必要的模块和项。

最近的文章

iOS 集成 Copilot 至 Xcode 实现智能化编程辅助

1. 前言GitHub 推出了一个强大的 AI 代码工具 Copilot(副驾驶),它能提供很好的代码建议,大大加快编程的开发速度。 Copilot 支持许多编程语言,包括 Swift,并可以在IDE上安装相应的扩展插件,方便地在 IDE 上使用 Copilot。 2. CopilotForXc …

, , , , 开始阅读
更早的文章

iOS 图像聚合加载视图 YCImageView 架构设计 & 使用

架构设计 执行设计 使用教程Objective - C使用 URL 加载12345678910111213141516171819202122232425262728293031/// 常规使用/// - Note: 不需要的回调直接传入 nil 即可/// - Note: 注意,以下所有 回调 …

, , , , 开始阅读
comments powered by Disqus