📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 1. 作用域
  • 1.1 项目的异同
  • 2. 模块
  • 2.1 私有性
  • 2.2 结构体以及枚举可见性
  • 3. 路径
  • 3.1 use 引入的基本规则
  • 3.2 使用外部包
  • 3.3 嵌套路径消除多个use

Was this helpful?

  1. RustInfo
  2. Info

包、crate、模块

[TOC]

1. 作用域

在编写程序时,一个核心的问题是作用域(scope).在Rust中有关作用域的概念可以使用package、crate、modules、path进行管理。

  • 包:允许构建、测试以及分享crate

  • crate:一个模块的树形结构,作为库或者二进制项目的结构

  • 模块:可以使用use关键字导入其他模块,可以控制作用域以及模块的私有性

  • 路径:一个指向函数,结构体,模块的命名

1.1 项目的异同

crate可以是一个二进制项目或者一个库项目,主要区别在于在src文件夹下的main.rs,lib.rsCargo 的约定是如果在代表包的 Cargo.toml 的同级目录下包含 src 目录且其中包含 main.rs 文件的话,Cargo 就知道这个包带有一个与包同名的二进制 crate,且 src/main.rs 就是 crate 根。另一个约定如果包目录中包含 src/lib.rs,则包带有与其同名的库 crate,且 src/lib.rs 是 crate 根。crate 根文件将由 Cargo 传递给 rustc 来实际构建库或者二进制项目。

一个包中至少包含一个二进制crate或者库crate,可以包含多个二进制crate,至多一个库crate。

2. 模块

可以使用关键字mod定义一个模块,可以在同一个文件中定义不同的模块,也可以在多个文件中进行模块的定义。包和crate用来构建二进制项目,src/main.rs, src/lib.rs用来作为crate根。从该根出发,以类似文件目录的形式逐层包含不同的模块。

crate
└── sound
    ├── instrument
    │   └── woodwind
    └── voice

2.1 私有性

在Rust中木块作为私有性边界(privacy boundary)。关于私有性的规则如下:

  • 所有项(函数,方法,结构体,枚举类型,模块,变量)默认都是私有的

  • 可以使用pub声明共有项

  • 不允许使用定由于当前模块子模块的私有代码

  • 允许使用任何定义于父模块或者当前模块的代码

也就是说,对于子模块中的不含有pub的项都不可以使用,但是对于所有服模块中的项都来可以直接使用。

mod sound {
    pub mod instrument {
        pub fn clarinet() {
            // 函数体
        }
    }
}

fn main() {
    // Absolute path
    crate::sound::instrument::clarinet();

    // Relative path
    sound::instrument::clarinet();
}

2.2 结构体以及枚举可见性

对于结构体而言,可以将结构体公有,在没一个字段的基准上也可以选择是否公有;对于枚举类型而言,如果将一个枚举类型声明为公有,那么所有的字段都是公有的。

3. 路径

路径用来引用模块树中的项。可以使用绝对路径或者相对路径引用模块中的内容,使用分隔符::隔开。

  • 绝对路径:从crate根开始的路径

  • 相对路径:使用self获取当前路径,super获取上一级路径

# fn main() {}
#
mod instrument {
    fn clarinet() {
        super::breathe_in();
    }
}

fn breathe_in() {
    // 函数体
}

3.1 use 引入的基本规则

使用use将其他模块引入当前作用域时,一般遵守以下规则。

  • 结构体、枚举类型,一般引入全路径,也就是在当前路径可以直接使用该类型

  • 函数或者方法一般引入父路径,使用super_name::func的语法进行调用

但是注意如果将不同模块的同名项引入作用域是不允许的。只能引入到模块。为了解决同名项的问题可以使用as关键字,将引入的项进行更名。

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

fn function1() -> Result {
#     Ok(())
}
fn function2() -> IoResult<()> {
#     Ok(())
}

注意使用use关键字将一些项引入当前作用域时,这些项默认都是私有的。如果希望调用编写的代码的代码能够像你一样在其自己的作用域内引用这些类型,可以结合 pub 和 use。这个技术被称为 “重导出”(re-exporting),因为这样做将项引入作用域并同时使其可供其他代码引入自己的作用域。

mod sound {
    pub mod instrument {
        pub fn clarinet() {
            // 函数体
        }
    }
}

mod performance_group {
    pub use crate::sound::instrument;

    pub fn clarinet_trio() {
        instrument::clarinet();
        instrument::clarinet();
        instrument::clarinet();
    }
}

fn main() {
    performance_group::clarinet_trio();
    performance_group::instrument::clarinet();
}

3.2 使用外部包

在cargo项目中如果需要使用外部包,可以在cargo.toml中添加依赖,需要使用=指明以来的版本。告诉cargo需要下载的依赖。然后就可以使用这些外部包。

3.3 嵌套路径消除多个use

可以使用嵌套路径,将多个属于同一个模块的项引入到当前作用域。

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

如果需要将一个模块中的所有公有项全部引入当前路径,可以使用use mod1::mod2::*;但是不推荐使用,因为如此难以推导作用域中有什么名称和它们是在何处定义的。glob 运算符经常用于测试模块 tests 中,这时会将所有内容引入作用域。

PreviousInfoNextRust 中的错误处理

Last updated 5 years ago

Was this helpful?