[package]
name = "guessing_game"
version = "0.1.0"
edition = "2018"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0"
[dependencies]
crate 是依赖树的顶点
crate 是编译的基本单元
cargo feature
对编译的 lib 进行条件编译,或者可选依赖。
如果是条件编译,加上 flag, --features。cargo.toml 中的 features section
使用cfg 表达式来体条件编译代码
在定义一个 feature 的的时候,能打开别的 feature。
有一个原则,A 和 B 都依赖 C crate,如果 A 和 B 各自依赖的 feature,如果如果不能共存(也就是开了一个 feature,另一个 feature 就用不了),那么 cargo 将直接编译错误。
cargo 在编译的时候,会将 A 和 B 各自依赖的 feature 进行编译
下面定义了一个 derive 的 feature,其依赖 sync crate
主要减少编译的时间
[package]
name = "foo"
[features]
derive = ["syn"]
[dependencies]
syn = { version = "1", optional = true }
Helps to manage multiple crates as a single project
例子
self 关键字用来访问同一个 mod 下的函数,
super 用来访问parent mod 下的函数,super 能访问在一个 mod 下访问 root functions
使用 super::super::foo 来访问祖父模块中的函数 foo1。
// main.rs
fn greet() -> String {
}
mod greetings {
pub fn hello() {
println!("hello world");
}
}
// calling private function in the same mod
// . Calling private functions of the same module
fn main() {
phrases::greet();
}
mod phrases {
pub fn greet() {
hello(); //or self::hello();
}
fn hello() {
println!("Hello, world!");
}
}
// 02. Calling private functions of the parent module
fn main() {
phrases::greetings::hello();
}
mod phrases {
fn private_fn() {
println!("Hello, world!");
}
pub mod greetings {
pub fn hello() {
super::private_fn();
}
}
}
// main.rs
fn main() {
greetings::hello();
}
fn hello() {
println!("Hello, world!");
}
mod greetings {
pub fn hello() {
super::hello();
}
}
在不同文件下访问 mod
// ↳ main.rs
mod greetings; // import greetings module
fn main() {
greetings::hello();
}
// ↳ greetings.rs
// ⭐️ no need to wrap the code with a mod declaration. File itself acts as a module.
pub fn hello() { // function has to be public to access from outside
println!("Hello, world!");
}
// 如果在 mod 下嵌套的其他的 mod,那么该 mod 必须声明为 pub
// ↳ main.rs
mod phrases;
fn main() {
phrases::greetings::hello();
}
// ↳ phrases.rs
// mod 嵌套
pub mod greetings { // ⭐️ module has to be public to access from outside
pub fn hello() {
println!("Hello, world!");
}
}
文件名作为名字空间的一部分
在不同目录中模块
// ↳ main.rs
mod greetings;
fn main() {
// 注意名字的写法
greetings::hello();
}
// ↳ greetings/mod.rs
pub fn hello() { // ⭐️ function has to be public to access from outside
println!("Hello, world!");
}
mod.rs in the directory module root is the entry point to the directory module.
All other files in that directory root, act as sub-modules of the directory module.
在上面的例子中目录作为名字空间的一部分
// ↳ main.rs
mod phrases;
fn main() {
// 在 mod 中声明了新的 mod,那么这部分也成为名字空间的一部分
phrases::greetings::hello();
}
// ↳ phrases/mod.rs
pub mod greetings { // ⭐️ module has to be public to access from outside
pub fn hello() {
println!("Hello, world!");
}
}
// # Think we run
cargo new --bin greetings
touch greetings/src/lib.rs
// # It generates,
.
├── Cargo.toml
└── src
├── lib.rs
└── main.rs
// # Think we modify following files
// 01. greetings/src/lib.rs
pub fn hello() {
println!("Hello, world!");
}
// 02. greetings/src/main.rs
extern crate greetings;
fn main() {
greetings::hello();
}
在 cargo.toml 声明的依赖 crates
多个 cargo 嵌套
// # Think we run
cargo new --bin phrases
cargo new phrases/greetings
// # It generates,
.
├── Cargo.toml
├── greetings
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
└── src
└── main.rs
// # Think we modify following files
// 01. phrases/Cargo.toml
[package]
name = "phrases"
version = "0.1.0"
authors = ["Dumindu Rajarathna"]
[dependencies]
// 注意这里的依赖
greetings = { path = "greetings" }
// 02. phrases/greetings/src/lib.rs
pub fn hello() {
println!("Hello, world!");
}
// 03. phrases/src/main.rs
// 引入 crates
extern crate greetings;
fn main() {
greetings::hello();
}
引入 git crates
// -- Cargo.toml --
[dependencies]
// 01. Get the latest commit on the master branch
rocket = { git = "https://github.com/SergioBenitez/Rocket" }
// 02. Get the latest commit of a specific branch
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "v0.3" }
// 03. Get a specific tag
rocket = { git = "https://github.com/SergioBenitez/Rocket", tag = "v0.3.2" }
// 04. Get a specific revision (on master or any branch, according to rev)
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "8183f636305cef4adaa9525506c33cbea72d1745" }
// src/lib.rs
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
文档中能使用markdown的格式,甚至能运行文档中的测试的例子:
Doc-tests my_crate
running 1 test
test src/lib.rs - add_one (line 5) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.
/// Adds one to the number given.
// --snip--
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
// -- Initial code without use keyword --
mod phrases {
pub mod greetings {
pub fn hello() {
println!("Hello, world!");
}
}
}
fn main() {
phrases::greetings::hello(); // using full path
}
// -- Usage of use keyword --
// 01. create alias for module
use phrases::greetings;
fn main() {
greetings::hello();
}
// 02. create alias for module elements
use phrases::greetings::hello;
fn main() {
hello();
}
// 03. customize names with as keyword
use phrases::greetings::hello as greet;
fn main() {
greet();
}
use keyword is used to import the elements of other crates including std
// -- 01. importing elements --
use std::fs::File;
fn main() {
File::create("empty.txt").expect("Can not create the file!");
}
// -- 02. importing module and elements--
std::fs::{self, File} //use std::fs; use std::fs::File;
fn main() {
fs::create_dir("some_dir").expect("Can not create the directry!");
File::create("some_dir/empty.txt").expect("Can not create the file!");
}
// -- 03. importing multiple elements
use std::fs::File;
use std::io::{BufReader, BufRead}; //use std::io::BufReader; use std::io::BufRead;
fn main() {
let file = File::open("src/hello.txt").expect("file not found");
let buf_reader = BufReader::new(file);
for line in buf_reader.lines() {
println!("{}", line.unwrap());
}
}
对于 std crates,不需要使用extern crate std;
pub use
当创建一个模块,you can export things from another module into your module.
So after that they can be accessed directly from your module. This is called re-exporting
// ↳ main.rs
mod phrases;
fn main() {
phrases::hello(); //not directly map
}
// ↳ phrases/mod.rs
pub mod greetings;
pub use self::greetings::hello; //re-export greetings::hello to phrases
// ↳ phrases/greetings.rs
pub fn hello() {
println!("Hello, world!");
}
注释
// Line comments
/* Block comments */
//! to write crate and module-level documentation,
Always avoid block comments, Use line comments instead.
参考资料
cargo 命令
自定义 cargo build
描述项目信息
cargo feature
默认 feature
条件依赖
project, package, crate, module 的区别
module tree
项目结构
代码组织
crates can be mappe to a
workspace
例子
使用 super::super::foo 来访问祖父模块中的函数 foo1。
在不同文件下访问 mod
在不同目录中模块
在 mod.rs 中访问子 mod
上面的例子,如果要直接访问 greetings 中的 hello,那么就应该在 phrase/mod.rs 中声明 greetings 为 pub
mod phrases::greetings
,但是能引入该模块的的 phrases::greetings::hello 这个函数到 phrases 模块下,这样就能在 main.rs 直接使用 phrases::hello()
crates
lib.rs 和 main.rs 在一块使用
对于二进制文件而言,这种方式比较常见
在 cargo.toml 声明的依赖 crates
多个 cargo 嵌套
引入 git crates
crate metadata
profile section
发布 crate 到 crates.io 中,文档的编写
cargo doc --open
,在本地打开文档,样子如下:contained items文档编写
workspace
use
类似于Cpp中的typedef,将一个元素的全路径名称绑定到一个新的名称
use keyword is used to import the elements of other crates including std
对于 std crates,不需要使用extern crate std;
pub use
注释
type/rust #public