
昨天我们学完了第六章相关知识点match
今天我们开启第七章之旅
packages、crates and modules现在我们在小打小闹,最多就一俩个fn和struct。
而一个最小的项目都可能有好几十个fn或者其他,并且随着后续开发,体量会继续增大。
这个时候如果我们的代码都堆在一起就会非常恶心和难管理。
这就需要用到今天学的知识了,大概是以下这五点。
packages和cratescrate有箱的意思,但是中文说的怪怪的。。。。所以这里都叫crate了。
crates我们之前的文章里也有简单的说过,这里再加深下印象。
crate是rust编译器一次处理的最小的单位。我们知道rust的编译器是rustc,而我们操作rustc编译的时候只能是传入文件名,再往下就不能了。所以得出结论,一个文件既是一个crate。
而在这个文件中可能包含着很多的module模块,所以一个crate就是一个·module tree,包含多个module。
crate有两种类型:
library crate,也就是一个库crate,默认入口是lib.rs文件, 他们不能被编译成可执行文件,也没有main函数。与之相反,他们会被当做功能性的库,可被其他项目引入,比如我们之前用过的Rand的库,大多数时候,当说一个crate的时候都是指的库crate。binary crate,二进制crate,他们编译后会变成可执行的文件,也就是.exe文件(window系统)。有个点需要注意,那就是默认是main.rs文件的main函数作为入口,不需要配置。而包packages相信大家都知道是啥了,这里简单说一下。
多个crate组合到一起,但不只是这样。它包含一个Cargo.toml的配置文件,用于配置项目。
有个点需要注意,那就是一个packages并不等价于一个project。它可以包含多个project,这些project共用同一个Cargo.toml文件。
一个packages至少拥有一个crate,可以包含多个binary crate, 但是只允许有一个library crate。
modules模块这玩意儿大家应该都很熟了,不过前端的开发应该对模块声明没有什么概念,因为工程化之后一个文件就是一个模块,如果你看过打包后的文件,其实一个立即执行函数,这就是一个模块。
扯远了,在rust中定义一个模块需要用到关键字mod,来看下例子
我们声明了一个module:animal。然后又在里面声明了dog、cat、fish三个mod。
module是允许嵌套的,module的名字规范是小写字母 + 下划线。
一个crate中可以允许有多个mod,一个module里也允许有多个module。
module里的东西默认是私有的(private),如果想要访问的话,需要开启public.
不过在这之前,我们要知道怎么使用module里的东西,我们来改下我们的module,给它加个函数方便我们调用。
我们在dog这个module里声明了一个eat的method。
可以看到访问module里的东西需要用::符号。
然后由于module默认私有,所以这里自然就会报错
然后我们可以通过pub关键字让module变成public
这个时候就没报错了
在遇到这个animal的module时,编译器会去找这个module的位置,首先会在当前文件里找,找不到会去到src/animal.rs,找不到又会找src/animal/mod.rs文件。
而遇到dog这个module的时候则会这么找:
src/animal/dog.rssrc/animal/dog/mod.rs另外有个点我们需要注意,那就是module里的东西是不能访问外部的东西的
这个点和作用域里的不同,那么要怎么用module外的东西呢?下面会说到。
path访问module上面已经简单地说到了,访问一个module里的东西需要::符号,而且默认是私有的。
我们来加深下印象。
其实访问一个crate有两种方式:
crate,比如crate::animal::dog表示从根crate开始找,还记得我们上面说的吗?crate是由多个module组成,是module tree,所以你直接从crate开始找就表示从根root开始找。animal::dog::eat就是一个相对路径,表示当前文件中的animal这个module里的dog这个module里的eat方法。所以上面那个找不到路径的报错我们可以使用绝对路径来访问
由于这个test方法是在文件最顶层的,所以用常规相对路径拿不到。
但如果我们还想用相对路径呢?官方提供了一个关键词super[4]
如果一个module能确定不会发生相对移动,那么用相对路径会是一个不错的选择。但是大多数情况下我们都是用绝对路径,因为这样会更安全。
现在我们都是在同一个文件中测试,但实际开发肯定是得跨文件的,所以我们来把module放到其他文件中。
官方推荐了一种项目规范[6] ,一般创建项目的时候src下默认会有一个main.rs,这个前面说过了是binary crate的入口,这个时候我们还需要在src文件夹下创建一个lib.rs文件。为什么要这么做呢?我们把通用(非业务)的代码都放到这个lib.rs文件中,而前面说过这个lib.rs是作为library crate的入口,会被编译成一个库,这个库到时候就能被其他项目使用。
真是一举俩得~ 双赢。
话不多说,我们在src下创建个lib.rs文件,然后我们再创建一个animal的文件,用来存放animal这个module,不过我们不需要把animal这个名字也移动过去,因为crate默认是当前文件名字,如果再把animal移动过去则别的地方要这样写animal::animal。
ok这样就拆分完了,接下来我们要在别的文件中引用这个animal crate
use来引入模块我们可以通过use关键字,直接引入模块里的东西,这样即保证了绝对路径的安全,又不用写那么长了。
先来看下同文件中怎么使用。
use crate::animal::dog,这样就能直接用dog::eat而不用crate::animal::dog::eat这样了。
当然,这个mod必须是pub的。
而我们现在拆分成多个文件了,那么我们来试下从别的文件里引入。
main.rs文件中
mod animal表示引入了animal这个module, 这样就能用这个animal.rs文件中的所有pub的mod了。
你也可以不用use关键字,直接animal::dog::eat也是可以的。
另外如果你不引入这个mod,你可以通过全局的路径引入,比如
concept是我们的package名字。
另外有一点,那就是一般我们想要放入lib中的crate都会抽一个专门的文件,比如这个animal,然后再引入lib.rs中,并且pub出去。比如:
有些module中的方法或者struct等的名字会重复,但由于module不同使得他们可以共存,这种时候我们就得确保上级路径也写了,但这样就未免会有些麻烦。
所幸rust提供了as关键字允许local name,就像js中的一样,可以重写名字。来看下例子
这个时候as就很有用了。
这样就可以啦。
今天我们把整个第七章都学完了,学了package、crate、module、pub、use、as等,都是一些概念,比较好懂。
如果觉得对你有帮助的话,请务必点个赞,谢谢~
居家办公就是爽,今天摸了一天鱼~
编辑于 2022-12-10 10:23・IP 属地广东