如果您有这样的目录 struct :

src/main.rs
src/module1/blah.rs
src/module1/blah2.rs
src/utils/logging.rs

如何使用其他文件中的函数?

从Rust教程中,听起来我应该能够做到:

main.rs

mod utils { pub mod logging; }
mod module1 { pub mod blah; }

fn main() {
    utils::logging::trace("Logging works");
    module1::blah::doit();
}

logging.rs

pub fn trace(msg: &str) {
    println!(": {}\n", msg);
}

blah.rs

mod blah2;
pub fn doit() {
    blah2::doit();
}

blah2.rs

mod utils { pub mod logging; }
pub fn doit() {
    utils::logging::trace("Blah2 invoked");
}

但是,这会产生一个错误:

error[E0583]: file not found for module `logging`
 --> src/main.rs:1:21
  |
1 | mod utils { pub mod logging; }
  |                     ^^^^^^^
  |
  = help: name the file either logging.rs or logging/mod.rs inside the directory "src/utils"

看来,沿着这条路径导入(即从mainmodule1/blah.rs)是可行的,导入对等点(即从blahblah2)是可行的,但从父范围导入不可行.

如果我使用魔法#[path]指令,我可以做到:

blah2.rs

#[path="../utils/logging.rs"]
mod logging;

pub fn doit() {
    logging::trace("Blah2 invoked");
}

我真的需要手动使用相对文件路径从父作用域级别导入内容吗?有没有更好的方法在铁 rust 中实现这一点?

在Python中,本地范围使用from .blah import x,但如果想要访问绝对路径,可以使用from project.namespace.blah import x.

推荐答案

我假设你想在顶层声明utilsutils::logging,只想从module1::blah::blah2中调用函数.模块的声明是用mod完成的,mod将模块插入AST并定义其规范的foo::bar::baz样式路径,与模块的正常交互(远离声明)是用use完成的.

// 主要的rs

mod utils {
    pub mod logging { // could be placed in utils/日志(log)记录.rs
        pub fn trace(msg: &str) {
            println!(": {}\n", msg);
        }
    }
}

mod module1 {
    pub mod blah { // in 模块1/诸如此类.rs
        mod blah2 { // in module1/blah2.rs
            // *** this line is the key, to bring utils into scope ***
            use crate::utils;

            pub fn doit() {
                utils::logging::trace("Blah2 invoked");
            }
        }

        pub fn doit() {
            blah2::doit();
        }
    }
}

fn main() {
    utils::logging::trace("Logging works");
    module1::blah::doit();
}

我唯一做的改变是blah2中的use crate::utils;行(在Rust 2015中,你也可以使用use utilsuse ::utils).有关use如何工作的更多详细信息,请参见the second half of this answer.relevant section of The Rust Programming Language也是一个合理的参考,尤其是这两个小节:

另外,请注意,我将其全部内联编写,将foo/bar.rs的内容直接放在mod foo { mod bar { <contents> } }中,将其更改为mod foo { mod bar; },并使用可用的相关文件,应该是相同的.

(顺便说一句,println(": {}\n", msg)打印两行新内容;println!已经包括一行(ln是"行"),print!(": {}\n", msg)println!(": {}", msg)只打印一行.)


要得到你想要的确切 struct 不是惯用的,你必须对blah2.rs的位置做一个改变:

src
├── 主要的rs
├── module1
│   ├── blah
│   │   └── blah2.rs
│   └── blah.rs
└── utils
    └── logging.rs

主要的rs

mod utils {
    pub mod logging;
}

mod module1 {
    pub mod blah;
}

fn main() {
    utils::logging::trace("Logging works");
    module1::blah::doit();
}

utils/日志(log)记录.rs

pub fn trace(msg: &str) { 
    println!(": {}\n", msg); 
}

模块1/诸如此类.rs

mod blah2;

pub fn doit() {
    blah2::doit();
}

模块1/诸如此类/诸如此类.rs(唯一需要更改的文件)

// this is the only change

// Rust 2015
// use utils; 

// Rust 2018    
use crate::utils;

pub fn doit() {
    utils::logging::trace("Blah2 invoked");
}

Rust相关问答推荐

Rust TcpStream不能在读取后写入,但可以在不读取的情况下写入.为什么?

如何为rust trait边界指定多种可能性

像这样的铁 rust 图案除了‘选项’之外,还有其他 Select 吗?

在本例中,为什么我不能一次多次borrow 可变变量?

为什么这个变量不需要是可变的?

为什么RefCell没有与常规引用相同的作用域?

Rust 中什么时候可以返回函数生成的字符串切片&str?

如何迭代存储在 struct 中的字符串向量而不移动它们?

如何使用tracing-subscriberRust crate 构建多编写者、全局过滤订阅者

Rust Axum 框架 - 解包安全吗?

.to_owned()、.clone() 和取消引用 (*) 之间有区别吗?

Rust FFI 和 CUDA C 性能差异

存储返回 impl Trait 作为特征对象的函数

str 和 String 的 Rust 生命周期

如果不满足条件,如何在 Rust 中引发错误

如何将参数传递给Rust 的线程?

在 Rust 中返回对枚举变体的引用是个好主意吗?

相交着色器从 SSBO 中读取零

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

为什么我不能将元素写入 Rust 数组中移动的位置,但我可以在元组中完成