Rust的包、单元包、模块、路径

我爱海鲸 2024-01-29 12:45:33 rust学习

简介Package, Crate,Module、path、use、更换rust源

1、Rust 的代码组织

代码组织主要包括:

   哪些细节可以暴露,哪些细节是私有的

   作用域内哪些名称有效

模块系统:

   Package(包): Cargo 的特性,让你构建、测试、共享crate

   Crate(单元包):一个模块树,它可产生一个 library或可执行文件

   Module(模块)、use:让你控制代码的组织、作用域、私有路径

   Path(路径):为 struct、function或module 等项命名的方式

Crate的类型:

   binary

   library

Crate Root:

   是源代码文件

   Rust编译器从这里开始,组成你的Crate的根Module

一个Package:

   包含1个Cargo.toml,它描述了如何构建这些Crates

   只能包含0-1个 library crate

   可以包含任意数量的 binary crate

   但必须至少包含一个crate (library 或binary)

Cargo 的惯例:

   src/main.rs:

      binary crate的crate root

      crate名与package名相同

   src/lib.rs:

      package 包含一个 library crate

      library crate 的 crate root

      crate 名与package名相同

Cargo 把crate root文件交给rustc来构建 library或 binary

一个Package 可以同时包含src/main.rs和 src/lib.rs

   一个binary crate,一个library crate

   名称与package名相同

一个Package可以有多个binary crate:

   文件放在 src/bin

   每个文件是单独的 binary crate

Crate的作用

   将相关功能组合到一个作用域内,便于在项目间进行共享

      防止冲突

      例如 rand crate,访问它的功能需要通过它的名字: rand

定义module来控制作用域和私有性

   Module:

      在一个crate内,将代码进行分组

      增加可读性,易于复用

      控制项目(item)的私有性。public、private

   建立 module:

      mod 关键字

      可嵌套

      可包含其它项(struct、enum、常量、trait、函数等)的定义

例如:在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() {}
    }
}

Module

src/main.rs和 src/lib.rs叫做crate roots:

   这两个文件(任意一个)的内容形成了名为crate的模块,位于整个模块树的根部

   整个模块树在隐式的crate模块下

2、路径(path)

   为了在Rust的模块中找到某个条目,需要使用路径

   路径的两种形式:

      绝对路径:从crate root开始,使用crate 名或字面值 crate

      相对路径:从当前模块开始,使用self,super或当前模块的标识符

路径至少由一个标识符组成,标识符之间使用::

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

pub fn eat_at_restaurant() {
    
    // 绝对路径
    crate::front_of_house::hosting::add_to_waitlist();
    
    // 相对路径
    front_of_house::hosting::add_to_waitlist();
}

私有边界( privacy boundary)

   模块不仅可以组织代码,还可以定义私有边界。

   如果想把函数或struct等设为私有,可以将它放到某个模块中。

   Rust中所有的条目(函数,方法,struct,enum,模块,常量〉默认是私有的。

   父级模块无法访问子模块中的私有条目

   子模块里可以使用所有祖先模块中的条目

pub关键字

   使用pub 关键字来将某些条目标记为公共的

super关键字

   super:用来访问父级模块路径中的内容,类似文件系统中的..

fn serve_order() {
    
}

mod back_of_house {
    fn fix_incorrect_order(){
        cook_order();
        super::serve_order();
    }

    fn cook_order() {
        
    }
}

pub struct

   pub放在 struct 前:

  • struct是公共的
  • - struct的字段默认是私有的

struct的字段需要单独设置pub来变成公有。

mod back_of_house {
   pub struct Breakfast {
        pub toast:String,
        season_fruit:String,
   }

   impl Breakfast {
       pub fn summer(toast:&str)->Breakfast {
           Breakfast {
            toast:String::from(toast),
            season_fruit:String::from("peachs"),
           }
       }
   }

}

pub fn eat_at_restaurant() {
    let mut meal = back_of_house::Breakfast::summer("Rye");
    // 这里是公有的,可以访问
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please",meal.toast);
    // 这里是私有的,不能访问
    meal.season_fruit = String::from("blueberries");
}

pub enum

   pub放在 enum前:

   enum是公共的

   enum 的变体也都是公共的

mod back_of_house {
    pub enum Appetizer {
        Soup,
        Salad,
    }
}

use关健字

可以使用use关键字将路径导入到作用域内

   仍遵循私有性规则

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

use crate::front_of_house::hosting;


pub fn eat_of_resttarurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

使用use来指定相对路径

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

use front_of_house::hosting;


pub fn eat_of_resttarurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

use的习惯用法

函数:将函数的父级模块引入作用域(指定到父级)

struct,enum,其它:指定完整路径(指定到本身)

use std::collections::HashMap;

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

同名条目:指定到父级

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


fn f1 () -> fmt::Result{

}

fn f2 () -> io::Result{

}

fn main() {

}

as关键字

   as关键字可以为引入的路径指定本地的别名

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


fn f1 () -> Result{

}

fn f2 () -> IoResult{

}

fn main() {

}

使用pub use重新导出名称

   使用use将路径(名称)导入到作用域内后,该名称在此作用域内是私有的。

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

pub use crate::front_of_house::hosting;


pub fn eat_of_resttarurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

pub use:重导出

   将条目引入作用域

   该条目可以被外部代码引入到它们的作用域

使用外部包(package)

   Cargo.toml添加依赖的包(package)

   https://crates.io/

   use将特定条目引入作用域

用法请参考:Rust的库

下载比较慢的时候 可以切换下载源 在.cargo文件夹下创建一个config文件 没有后缀,贴入下面的代码

[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
# 指定镜像
replace-with = 'ustc' # 如:tuna、ustc,或者 rustcc 指定一个即可

# 中国科学技术大学
[source.ustc]
registry = "https://mirrors.ustc.edu.cn/crates.io-index"

# 清华大学
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git" 

# rustcc社区
[source.rustcc]
registry = "https://code.aliyun.com/rustcc/crates.io-index.git"

标准库(std)也被当做外部包

   不需要修改Cargo.toml来包含std

   需要使用use将std 中的特定条目引入当前作用域

使用嵌套路径清理大量的use语句

   如果使用同一个包或模块下的多个条目

   可使用嵌套路径在同一行内将上述条目进行引入:

   路径相同的部分::{路径差异的部分}

use std::{cmp::Ordering,io};

use std::io::{self, Write};

fn main() {


}

通配符*

使用*可以把路径中所有的公共条目都引入到作用域。

注意:谨慎使用应用场景:

   测试。

   将所有被测试代码引入到tests模块

3、将模块内容移动到其它文件

   模块定义时,如果模块名后边是“;”,而不是代码块:

      Rust会从与模块同名的文件中加载内容

      模块树的结构不会变化

如:

lib.rs:

mod front_of_house;

pub use crate::front_of_house::hosting;


pub fn eat_of_resttarurant() {
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
    hosting::add_to_waitlist();
}

front_of_house.rs:

pub mod hosting;

创建front_of_house文件夹:hosting.rs:

pub fn add_to_waitlist(){}

随着模块逐渐变大,该技术让你可以把模块的内容移动到其它文件中

 

你好:我的2025