初面网初面网

代码组织

其实就是模块化,将不同的功能写进或编译进不同的文件,从而方便管理和复用。在Rust里用三个概念完成这件事:箱、包、模块

  • 箱(Crate)

箱,二进制程序文件或者库文件,以树状结构存在,树根是编译器开始运行时编译的源文件所编译的程序,存于包。

  • 包(Package)

当我们使用 Cargo 执行 new 命令创建 Rust 工程时,工程目录下会建立一个 Cargo.toml 文件。工程的实质就是一个包,包必须由一个 Cargo.toml 文件来管理,该文件描述了包的基本信息以及依赖项。

一个包最多包含一个库"箱",可以包含任意数量的二进制"箱",但是至少包含一个"箱"(不管是库还是二进制"箱")。

当使用 cargo new 命令创建完包之后,src 目录下会生成一个 main.rs 源文件,Cargo 默认这个文件为二进制箱的根,编译之后的二进制箱将与包名相同。

如果在创建Package的时候带有--lib参数,那么这个包就是一个库包,入口是src/lib.rs

  • 模块(Module)

相当于Java中类的概念,Rust中使用Module包含并管理某一些函数和属性。

mod nation {
  mod government {
      fn govern() {}
  }
  mod congress {
      fn legislate() {}
  }
  mod court {
      fn judicial() {}
  }
}

这种构建方式最终会形成一棵树,能够在文件系统中访问。在别的系统中,目录结构的分割符可能是斜杠,在Rust中是::

像上面这个解构,可以如下路径访问:

crate::nation::government::govern();

这是govern函数的绝对路径。相对路径为:

nation::government::govern();

路径如此,但是实际访问会发现,govern其实是私有(private)的。

另外需要知道的是,每个rust文件实际上就是一个模块

// main.rs
mod second_module;

fn main() {
  println!("This is the main module.");
  println!("{}", second_module::message());
}

// second_module.rs
pub fn message() -> String {
  String::from("This is the 2nd module.")
}

// 注意上面是两个不同的rust文件,一个是main文件,一个是second_module

访问权限

公共(public)和私有(private)。默认为私有。设为公共需要pub关键字。有三种pub写法:

  • pub,成员对模块可见
  • pub(self),成员对模块内的子模块可见
  • pub(crate):成员对整个crate可见
mod nation{
  pub mod government{
    pub fn govern(){}
  }

  mod court{
    fn judicial(){
      super::congress::legislate(); // 在这里,super指代nation。实际上super指代承载当前mod的那个mod
    }
  }
}

fn main(){
  nation::government::govern();
}

模块中的结构体本身默认是私有的,字段默认也私有。需要pub设置才能变为公有。但是对于定义结构体的模块内的方法来说,结构体的字段是公有的。

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

  impl Breakfast {
    pub fn summer(toast: &str) -> Breakfast {
      Breakfast {
        toast: String::from(toast),
        seasonal_fruit: String::from("peaches"),
      }
    }
  }
}
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);
}
fn main() {
  eat_at_restaurant()
}

枚举本身默认是私有的,需要pub设置为公有。枚举内含字段不具有私有性质,可随意访问。

use关键字

将模块标识符引入当前作用域。说白了,就是为了解决局部模块路径过长的问题

mod nation {
  pub mod government {
    pub fn govern() {}
  }
  pub fn govern() {}
}

use crate::nation::government::govern;
use crate::nation::govern as nation_govern; // 重名时可以起个别名

fn main() {
  nation_govern();
  govern();
}

// 如果不用use,那么main里使用的时候还是要用crate::nation::government::govern这样长串的路径
// 有多少次调用就要写多少次这样的长串,非常麻烦。use就是为了解决这样的麻烦而存在


/* 下面是use和pub一块使用的场景
mod nation {
  pub mod government {
    pub fn govern() {}
  }
  pub use government::govern;
}

fn main() {
  nation::govern();
}
*/

学会了导入模块,我们可以使用官方库和第三方库进行更便捷的开发了

官方库地址

use std::f64::consts::PI;

fn main() {
  println!("{}", (PI / 2.0).sin());
}

项目目录结构

例如src目录下有以下文件:

src/main.rs
src/second_module.rs
src/third_module.rs

其中main.rs是入口文件,second_module.rs和third_module.rs是两个模块。

main.rs中可以使用second_module::message()来调用third_module.rs中的message函数。

use third_module::message;

如果是以mod开头的文件,那么这个文件就是一个模块。

mod second_module;

在second_module.rs中可能的代码是:

pub fn message() -> String {
  String::from("This is the 2nd module.")
}

更新于 2026/6/10