Rust的模块化系统: 包Packages, 箱Crates, 和模块Modules

知乎 · · 396 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
  • 包 Packages: Cargo提供的让我们创建, 测试和分享Crates的工具.
  • 箱 Crates: 提供类库或可执行文件的模块树
  • 模块 Modules and use: 管理和组织路径, 及其作用域和访问权限
  • 路径 Paths: 如结构体(structs), 函数(function), 或模块(module)等事物的命名方式

包(Packages)和箱(Crates)

包(Package)通过Cargo创建. 每一个包(Package)都有一个Cargo.toml文件. 包(Package)包含箱(Crates)的规则如下:

  1. 只能包含0或1个类库箱(library crates)
  2. 可以包含任意多个二进制箱(binary crates)
  3. 至少有一个箱(Crate), 可以是类库箱(library crates), 也可以是二进制箱(binary crates)

创建二进制包(binary package)

❯ cargo new my-project
     Created binary (application) `my-project` package
❯ tree my-project
my-project
├── Cargo.toml
└── src
    └── main.rs

创建类库包(library package)

❯ cargo new --lib my-lib
     Created library `my-lib` package
❯ tree my-lib
my-lib
├── Cargo.toml
└── src
    └── lib.rs

默认, 一个箱(crate):

  • src/main.rs 是二进制箱(binary crate)的根文件, 该箱(crate)与包(package)同名
  • src/lib.rs 是类库箱(library crate)的根文件, 该箱(crate)与包(package)同名

多个二进制箱(binary crates): 在src/bin目录下创建.rs文件, 每个文件对应一个二进制箱(binary crate).

模块Modules

模块通过关键字mod加模块定义, 例如:

// Filename: src/lib.rs 

mod front_of_house {
    mod hosting {
        fn add_to_waitlist() {}

        fn seat_at_table() {}
    }

    mod serving {
        fn take_order() {}

        fn serve_order() {}

        fn take_payment() {}
    }
}

文件src/main.rssrc/lib.rs, 对应的模块是crate, 箱(crate)的模块结构(module structure), 也叫做模块树(module tree):

crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         ├── serve_order
         └── take_payment

注: 模块crate默认存在, 不需要通过关键字mod方式来定义

路径Paths

与文件系统类似, 文件系统的根节点是/, 箱(crate)的根节点是crate.

  • 绝对路径, 从箱(crate)的根节点开始, 箱(crate)的名称, 或crate
  • 相对路径, 从当前模块开始, 可以使用self, super
// 绝对路径 Absolute path
crate::front_of_house::hosting::add_to_waitlist();

// 相对路径 Relative path
front_of_house::hosting::add_to_waitlist();

访问权限

  • 所有元素, 函数functions, 方法methods, 结构体structs, 枚举enum, 模块modules, 常量constants, 默认是私有的, 对外公开(public), 需要通过关键字pub声明
    • 即便是共有的结构体(public structs), 内部的元素(fields)和方法(methods)仍是私有的(private)
    • 共有的枚举(public enums), 其所有变天(variants)也同为共有(public)
  • 父模块中的元素, 不能使用子模块中的私有元素
  • 子模块中的元素, 可以使用父模块的元素

use

使用关键字use简化路径Paths, 类似文件系统中的'symbolic link'.

一些惯常用法

调用其它模块函数时, 通过use引入其所在的模块(module)

use some_mod;

fn main() {
    some_mod::some_fn();
}

调用其它模块结构体struct, 枚举enum,通过全路径引入,

use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert(1, 2);
}

有命名冲突时, 引入父模块

use std::fmt;
use std::io;

fn function1() -> fmt::Result {
    // --snip--
}

fn function2() -> io::Result<()> {
    // --snip--
}

或用as解决命名冲突的问题

use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --snip--
}

fn function2() -> IoResult<()> {
    // --snip--
}

引入同一个模块module或包package中的多个元素

use std::{cmp::Ordering, io};
use std::io::{self, Write}; // 引入 std::io 和 std::io::Write

引入模块下所有共有元素, 需谨慎使用, 一般在测试时或预加载时使用

use std::collections::*;

re-exporting names with pub use (暂且跳过)

使用外部包(External Packages)

在文件Cargo.toml中添加依赖[dependencies], Cargo从crates.io下载所需要的依赖包.

[dependencies]
rand = "0.5.5"

引入rand中的Rng特性(trait)

use rand::Rng;
fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);
}

本文来自:知乎

感谢作者:知乎

查看原文:Rust的模块化系统: 包Packages, 箱Crates, 和模块Modules

关注本站微信公众号(和以上内容无关)InfraPub ,扫码关注:InfraPub

396 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传