已发布·持续改进
Rust 指南 · 4/6
本章目前仅提供英文版。
As a program grows you need to split it up, pull in libraries written by others, and sometimes manage several related projects together. This chapter covers Rust's module system, dependencies from crates.io, workspaces and Cargo features.
| Term | Meaning |
|---|---|
| Package | What one Cargo.toml describes; contains one or more crates |
| Crate | A unit of compilation: a binary or a library |
| Module | A namespace inside a crate that also controls visibility |
| Path | A name like crate::net::connect that points to an item |
A binary crate is rooted at src/main.rs and a library crate at src/lib.rs. Libraries published on crates.io are also simply called crates.
mod declares a module. Everything inside is private by default; mark items pub to expose them. Making a struct pub does not expose its fields, each field needs its own pub. use brings a long path into scope under a short name.
mod geometry {
pub mod shapes {
pub struct Circle {
pub radius: f64,
}
impl Circle {
pub fn area(&self) -> f64 {
std::f64::consts::PI * self.radius * self.radius
}
}
}
pub fn double(x: f64) -> f64 {
helper(x) * 2.0
}
// No pub: only visible inside the geometry module
fn helper(x: f64) -> f64 {
x
}
}
use geometry::shapes::Circle;
fn main() {
let c = Circle { radius: 2.0 };
println!("{:.2}", c.area());
println!("{}", geometry::double(1.5));
}Paths start from the crate root with crate::, from the current module with self::, or from the parent with super::. For finer control, pub(crate) exposes an item within the crate only, and pub(super) to the parent module only.
A declaration without a body, such as mod config;, tells the compiler to load src/config.rs (or the older style src/config/mod.rs). Submodules of config go into a src/config/ directory.
// src/main.rs
mod config;
use config::Config;
fn main() {
let cfg = Config::new();
println!("port = {}", cfg.port);
}// src/config.rs
pub struct Config {
pub port: u16,
}
impl Config {
pub fn new() -> Self {
Config { port: 8080 }
}
}A use declaration can import several items at once (use std::collections::{HashMap, HashSet};), rename them (use std::io::Result as IoResult;) or re-export them. Libraries often pub use deeply nested items so users get a flat, friendly API.
Public libraries live on crates.io, and their API docs are on docs.rs. The easiest way to add one is cargo add:
cargo add serde --features derive
cargo add serde_json
cargo add --dev pretty_assertions
cargo update # bump Cargo.lock within compatible rangesCargo records them in the manifest. A requirement of "1" means any SemVer-compatible 1.x release; the exact version chosen is pinned in Cargo.lock.
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
[dev-dependencies]
pretty_assertions = "1"You can now refer to the crate by name. Hyphens in a crate name become underscores in code.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct User {
name: String,
age: u32,
}
fn main() -> Result<(), serde_json::Error> {
let user = User { name: "kim".to_string(), age: 30 };
let json = serde_json::to_string(&user)?;
println!("{json}"); // {"name":"kim","age":30}
let back: User = serde_json::from_str(&json)?;
println!("{back:?}");
Ok(())
}A workspace groups several packages in one repository. Members share a single Cargo.lock and target/ directory, so builds are faster and versions stay consistent.
# Root Cargo.toml
[workspace]
members = ["app", "shared"]
resolver = "2"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
# app/Cargo.toml
[dependencies]
shared = { path = "../shared" }
serde = { workspace = true }Declare a version once under [workspace.dependencies] and inherit it with workspace = true. Target one member with -p, as in cargo build -p app or cargo run -p app. A virtual workspace (no root package) should set resolver explicitly: "2" matches the 2021 edition, "3" the 2024 edition.
Features are optional, named switches for conditional compilation. They are commonly used to keep heavy dependencies out unless someone asks for them.
[features]
default = ["json"]
json = ["dep:serde_json"]
[dependencies]
serde_json = { version = "1", optional = true }In code, gate items with #[cfg(feature = "json")]. Build with cargo build --no-default-features to turn defaults off, or cargo build --features json to turn a feature on.
mod name; loads a file of the same name; use shortens paths.cargo add; Cargo.lock pins the exact versions.
0 条评论
登录 · 登录后即可发表评论。
来发表第一条评论吧。