Essential Standard Traits
Default
The Default trait provides a standard zero-argument constructor (Default::default()) that produces a sensible initial or empty value for a type.
Trait Definition
pub trait Default: Sized {
fn default() -> Self;
}
Standard library types implement Default with their natural empty or zero states:
| Type | Default::default() Value |
|---|---|
Numeric types (i32, u64, f64, etc.) |
0 or 0.0 |
bool |
false |
char |
'\0' |
String, Vec<T>, HashMap<K, V> |
Empty container (does not allocate heap memory) |
Option<T> |
None (even if T does not implement Default) |
Deriving Default on Structs and Enums
Applying #[derive(Default)] to a struct initializes every field with Default::default(). Applying #[derive(Default)] to an enum requires marking exactly one unit variant with #[default]:
#[derive(Debug, Default)]
enum LogLevel {
Debug,
#[default]
Info,
Warn,
Error,
}
#[derive(Debug, Default)]
struct AppOptions {
level: LogLevel,
max_retries: u32,
log_path: Option<String>,
}
fn main() {
let opts = AppOptions::default();
println!("{opts:#?}");
}
AppOptions {
level: Info,
max_retries: 0,
log_path: None,
}
Struct Update Syntax with ..Default::default()
Combining struct update syntax with Default::default() lets callers override only specific fields while leaving all remaining fields at their defaults:
#[derive(Debug)]
struct HttpClientConfig {
timeout_ms: u64,
follow_redirects: bool,
max_connections: usize,
}
impl Default for HttpClientConfig {
fn default() -> Self {
Self {
timeout_ms: 5_000,
follow_redirects: true,
max_connections: 32,
}
}
}
fn main() {
let custom = HttpClientConfig {
timeout_ms: 15_000,
..Default::default()
};
println!("{custom:?}");
}
HttpClientConfig { timeout_ms: 15000, follow_redirects: true, max_connections: 32 }
Standard Library Methods Powered by Default
Implementing Default unlocks convenience methods across the standard library:
Option::unwrap_or_default()returns the containedSome(v)orT::default()ifNone.Result::unwrap_or_default()returns theOk(v)value orT::default()onErr(_).std::mem::take(&mut dest)replacesdestwithT::default()and returns the old value without requiringT: Clone.HashMap::entry(k).or_default()insertsV::default()if the key is absent and returns&mut V.