如何在Rust 2015中从一个模块到另一个模块执行基本导入/包含功能?

vil*_*vil 41 module rust

我找不到如何将函数从一个文件(模块)包含(或导入,注入或其他一些单词)到另一个文件.

我开始一个新项目

$ cd ~/projects
$ cargo new proj --bin
$ cd proj
$ tree
.
|
-- Cargo.toml
-- src
   |
   -- main.rs
Run Code Online (Sandbox Code Playgroud)

我使用以下代码修改main.rs并创建一个新文件a.rs(在srcdir中):

main.rs

fn main() {
    println!("{}", a::foo());
}
Run Code Online (Sandbox Code Playgroud)

a.rs

pub fn foo() -> i32 { 42 }
Run Code Online (Sandbox Code Playgroud)

我运行项目cargo run并得到错误:

error[E0433]: failed to resolve: use of undeclared type or module `a`
 --> src/main.rs:2:20
  |
2 |     println!("{}", a::foo());
  |                    ^ use of undeclared type or module `a`
Run Code Online (Sandbox Code Playgroud)

似乎我需要以a某种方式导入.我尝试添加以下内容作为第一行main.rs

  • use a;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a;
      |     ^ no `a` in the root
    
    Run Code Online (Sandbox Code Playgroud)
  • use a::*;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a::*;
      |     ^ maybe a missing `extern crate a;`?
    
    error[E0433]: failed to resolve: use of undeclared type or module `a`
     --> src/main.rs:4:20
      |
    4 |     println!("{}", a::foo());
      |                    ^ use of undeclared type or module `a`
    
    Run Code Online (Sandbox Code Playgroud)
  • use a::foo;

    error[E0432]: unresolved import `a`
     --> src/main.rs:1:5
      |
    1 | use a::foo;
      |     ^ maybe a missing `extern crate a;`?
    
    error[E0433]: failed to resolve: use of undeclared type or module `a`
     --> src/main.rs:4:20
      |
    4 |     println!("{}", a::foo());
      |                    ^ use of undeclared type or module `a`
    
    Run Code Online (Sandbox Code Playgroud)
  • extern crate a; use a::foo;

    error[E0463]: can't find crate for `a`
     --> src/main.rs:1:1
      |
    1 | extern crate a;
      | ^^^^^^^^^^^^^^^ can't find crate
    
    Run Code Online (Sandbox Code Playgroud)
  • extern crate proj; use proj::a::foo;

    error[E0463]: can't find crate for `proj`
     --> src/main.rs:1:1
      |
    1 | extern crate proj;
      | ^^^^^^^^^^^^^^^^^^ can't find crate
    
    Run Code Online (Sandbox Code Playgroud)

我已阅读指南,但仍无法弄清楚如何进口.

o11*_*11c 39

在mainish模块(main.rs,lib.rs或subdir/mod.rs)中,您需要编写mod a;要在整个项目(或子目录)中使用的所有其他模块.

在任何其他模块中,您需要编写use a;use a::foo;

你不是唯一一个被这个混淆的人,而且肯定可以做得更好,但对模块系统的任何改变都会被拒绝为"太混乱".

编辑:这个答案是为"Rust 2015"语言标准编写的.对"Rust 2018"标准进行了更改,请参阅此博客文章.

  • `但是对模块系统的任何改变都会被拒绝,因为"太混乱了"`现有的模块系统"太混乱"了. (26认同)
  • 尽管多次阅读了有关模块的文档,但我确实花了 40 分钟才找到您在这里所说的内容。我在大约 3 种语言方面拥有多年的丰富经验,我猜总共大约有 10 种语言。到目前为止,Rust 中的模块系统是我见过的最不必要的过度复杂化...... (4认同)
  • @voithos您的main.rs或lib.rs以及通过`mod`指令递归反转的所有文件将被编译为一个包.这是编译的单位. (3认同)
  • 我花了**一个小时**试图解决这个问题.没有其他语言的导入系统具有如此多的不同关键字,含义,细微差别和非显而易见的功能. (3认同)

Lui*_*uso 16

在Rust中,有一些关键字可以处理模块:

extern crate

extern crate填补了Cargo和Rust之间的空白.我们在.rs文件中编写代码,这个文件可以编译rustc.Cargo将管理外部依赖和调用rustc.该extern crate ...行告诉编译器查找此命名空间,因此它是明确的.

编者注 - extern crate如果您使用的是Rust 2018版本,则在许多情况下不需要.

mod

mod 有两个用途:

  • 当与花括号一起使用时,它声明一个模块(命名空间).
  • 当只使用名称时,它将在本地文件系统中查找模块.

模块可以是:

  • 扩展名为.rs的文件
  • 一个名为mod.rs的文件夹

use

use导入命名空间.我们需要在使用之前宣布我们将要使用的内容.use子句非常严格,如果我们声明use module1::moduleA;没有其他模块module1可用但是moduleA.星号(*)可用于使用模块中的所有内容:use module1::*;.集合也可以使用:use module1::{moduleA, moduleB};

一个例子:

| main.rs
|- module1
      |- mod.rs
      |- moduleA.rs
      |- moduleB.rs
Run Code Online (Sandbox Code Playgroud)

mod.rs包含:

pub mod moduleA; // declare a child module
pub mod moduleB; // declare a child module
Run Code Online (Sandbox Code Playgroud)

main.rs包含:

///  ======
// use what Cargo downloaded
extern crate that_one_thing_i_need;

///  ======

mod module1; // declare a child module

// some local stuff I want to scope
mod local {
    pub fn my_function() {}
}

//   ======

// make the symbols locally available:
use module1::moduleA::*;
use module1::moduleB::{functionX, moduleY, typeZ};

// we still need to announce what stuff from the external crate
// we want to use:
// We can do local aliases that will be valid in this one file.
use that_one_thing_i_need::fancy_stuff as fs;

///  ======

fn main() {
    // we can use anything here from the namespaces we are using:
    //      moduleA
    //      functionX
    //      moduleY
    //      typeZ
    //      fs

    // We can access stuff by navigating from the outermost visible
    // module name
    local::my_function();
}
Run Code Online (Sandbox Code Playgroud)

符号仅可在模块内使用.如果你想跨越这个障碍(即使在本地声明的模块上),我们需要使用关键字将它们公开pub.


Fra*_*asa 6

我参加聚会很晚了,但是将代码拆分为多个文件而不过多影响范围的一种方法如下。

想象一下这样的文件夹结构,用于书籍处理库:

src/
  lib.rs
  author.rs
  book.rs
Run Code Online (Sandbox Code Playgroud)

你可以做:

src/
  lib.rs
  author.rs
  book.rs
Run Code Online (Sandbox Code Playgroud)

此结构模拟 Go 模块(文件夹中的所有内容似乎都在同一范围内)。

另一种方法是(更像Python风格):

// lib.rs
// --------------
mod author;
use author::*;
mod book;
use book::*;

// author.rs
// --------------
struct Author {
    name: String,
    birth_year: i32,
}

// book.rs
// --------------
use super::*;

struct Book {
   title: String,
   author: Author,  // Author is in scope
   isbn: i64,
}
Run Code Online (Sandbox Code Playgroud)