在Rust模块系统中,有诸多的概念和用法,不容易搞清楚,理一下,很有必要。
cargo是从包的根目录开始找相应的文件的。

一、packages、crates、modules

packages: 通过cargo new 创建;
crates: 通过cargo new --lib 创建。有根包和子包。即一个根包下可以包含多个子包。
modules: 通过关键字mod加模块定义

二、各种用法

src下有同个级:兄弟、父、子三个层级。

1、mod

往往是引入与当前文件同级的文件夹下(兄弟模块下)的文件。

2、crate

代表引用当前文件同级的文件。为同级文件时,意义和self相同。但如果是同级文件夹,不能混用。

3、super

super:代表当前文件的上一级目录(父模块) 。super后面可以直接接函数。也可以接“*”,表示所有函数。

4、self

见crate

5、pub use

Example	Explanation
mod m {}	Define a module, BK EX REF get definition from inside {}. ↓
mod m;	Define a module, get definition from m.rs or m/mod.rs. ↓
a::b	Namespace path EX REF to element b within a (mod, enum, ...).
     ::b	Search b relative to crate root. 🗑️
     crate::b	Search b relative to crate root. '18
     self::b	Search b relative to current module.
     super::b	Search b relative to parent module.
use a::b;	Use EX REF b directly in this scope without requiring a anymore.
use a::{b, c};	Same, but bring b and c into scope.
use a::b as x;	Bring b into scope but name x, like use std::error::Error as E.
use a::b as _;	Bring b anonymously into scope, useful for traits with conflicting names.
use a::*;	Bring everything from a into scope.
pub use a::b;	Bring a::b into scope and reexport from here.

三、桥

在src下,往往有一个子目录,比如名字叫core. 里面还有两个文件,read.rs,write.rs.此时,需要有一个文件把这两个文件串起来。
此时,可以在core目录同级,建一个core.rs文件,把core目录下的两个文件串起来,对外可见。
我称这种与目录相同的rs文件为桥(个人定义,不规范)文件。

比如:

pub mod a;
pub mod c;
pub use a::*; //不能省
pub use c::*;//不能省

四、实例1

1、具体的例子
相应的结构:
在这里插入图片描述
(1)a.rs

pub fn a_echo(){
    println!("a_echo!");
}

(2)c.rs

注意,crate不能用self替换crate。

use crate::src_a::a::*;
pub fn c_echo(){
    println!("c_echo!");
    a_echo();
}

(3)b.rs

use crate::src_a::a_echo;
//如何引入a.rs或c.rs中的函数
pub fn b_echo(){
    println!("b_echo! => call a()!");
    a_echo();

}

(4)src_a.rs

pub mod a;
pub mod c;
pub use a::*;
pub use c::*;

(5)src_b.rs

pub mod b;
pub use b::*;

(6)main.rs
crate和self可以互相替代。

pub mod src_a;
pub mod src_b;
pub use self::src_a::*;
pub use crate::src_b::*;

fn main() {
    println!("Hello, world!");
    src_a::a_echo();
    src_b::b_echo();
}

2、解决的问题:

(1) c.rs =>调用a.rs 中函数
(2) b.rs =>调用a.rs 中函数
(3)main.rs =>调用a.rs; 调用c.rs中函数;必须要使用“桥”。

3、src_a.rs和src_b.rs相当于分别是a.rs和c.rs与b.rs的代理。

在这里插入图片描述
五、实例2,更进一步

如果在rust_test中,src外,还有一个lib, b。
b是通过在rust_test中cargo new --lib d而来。
b是一个单独的库文件,

base) PS D:\rust_test\d> cd src
(base) PS D:\rust_test\d\src> tree /f
卷 新加卷 的文件夹 PATH 列表  
卷序列号为 6E25-CA92
D:.
    lib.rs

没有子文件夹

(base) PS D:\rust_test\d\src> 

lib.rs的文件:

pub fn d_echo(){
    println!("d_echo!");
}

那么,在rust_test中的main.rs如何调用d中lib函数,d_echo()?

1、首先要在rust_test的toml文件中进行修改,增加对d的依赖。

[dependencies]

d = { path = "../rust_test/d" }

2、在main.rs中:

直接使用路径表达即可。
在这里插入图片描述
六、有趣的mod.rs

还有一种桥的方法是mod.rs.
在这里插入图片描述
在上面,新建了一个src_e文件夹,下面有e.rs,内容如下:

pub fn e_echo(){
    println!("e_echo!");
}

此时,如果在内部再建立一个mod.rs的话,那么,mod.rs也是一种桥。可以让外部更方面地访问到e.rs.

但是,这种情况和外部建立一个与文件夹同名的rs文件有所不同。

e_echo()函数的前面路径是e,不再是src_e了。

六、main.rs同级f.rs

f.rs是位于main.rs同级文件。

pub fn f_echo(){
    println!("f_echo!");
}

在main.rs中调用f.rs中函数,可以用mod f;
在这里插入图片描述

七、src下 互相调用
举例:g.rs调用同一src下的f.rs.
在这里插入图片描述
八、其中的一些error

error[E0432]: unresolved import crate::xxxx

提醒:在src下的所有文档,要在main.rs中,引入src所有文件;
比如,这里src下有:f.rs; g.rs; 则:

mod f;
mod g; 

否则在其它地方使用:
use crate::g

感觉好象crate也用对了,但是就是一直出现上述类似的问题。

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐