Modules and packages
Structs and private fields only make sense once a module hides them. This lesson is the crate, then Cargo’s dependency file. Generics come after, because they are a language feature, not a package feature.
Modules and visibility
A crate is one compilation unit, a binary or a library. A package is the Cargo.toml that builds one or more crates. A module is a namespace inside a crate.
lib.rs is the root. mod auth; loads auth.rs or auth/mod.rs. mod routes; does the same. An inline mod { } is the same idea in one file, which is all a single lesson file can show.
| Mark | Who can see the name |
|---|---|
| (none) | Only the parent module |
pub | Outside the module |
pub(crate) | The whole crate |
pub(super) | The parent module |
pub(in path) | One path you name |
Private fields plus public methods are how a type keeps its invariant.
| Path | Starts from |
|---|---|
crate::auth::login | This crate |
super::helpers | The parent module |
std::collections::HashMap | The standard library |
| as | Renames an import |
pub use auth::User | Re-exports a name so callers do not need the inner path |
| The prelude | Already imports Option, Result, Vec, and the other names you have been using without a use line |
| A workspace | Lists members, one lockfile, and one target directory. That is how a monorepo shares versions. |
mod inventory {
pub struct Item {
pub name: String,
sku: String,
}
impl Item {
pub fn new(name: &str, sku: &str) -> Self {
Self { name: name.to_string(), sku: sku.to_string() }
}
pub fn sku(&self) -> &str {
&self.sku
}
}
}
fn main() {
let item = inventory::Item::new("bolt", "B-1");
println!("{} {}", item.name, item.sku());
}Dependencies, features, and versions
| Cargo.toml table | Used for |
|---|---|
| dependencies | The program itself |
| dev-dependencies | Tests |
| build-dependencies | Build scripts |
A version of 1.2.3 for a 1.0 crate means compatible updates inside 1.x. A 0.x crate may break between minor numbers. Prefer a caret range such as "1" and let Cargo.lock pin the exact build for a binary. Commit that lockfile.
Features are compile-time flags: serde with derive, tokio with a runtime. cfg(feature = "json") compiles a module only when that flag is on.
fn main() {
println!("dependencies live in Cargo.toml, not in this file");
println!("cargo tree, cargo update, and cargo check are the daily tools");
}