SoFunction
Updated on 2025-04-13

Detailed explanation of how to use the #[derive] attribute in Rust

In Rust, #[derive] is a property that automatically generates common implementations for types, such as Clone, Debug, etc. It greatly reduces duplicate code while ensuring implementation correctness and consistency.

Basic syntax

#[derive(Trait1, Trait2, ...)]
struct MyStruct {
    field1: Type1,
    field2: Type2,
}
  • Function: Automatically generates the implementation of the specified features.
  • Object of action: Can be used for struct, enum, and union.

Common #[derive] features

Debug: Automatically generates a debug representation of type, used for formatting output (usually used for printing or debugging).

#[derive(Debug)]
struct MyStruct {
    x: i32,
    y: f64,
}

fn main() {
    let s = MyStruct { x: 10, y: 3.14 };
    println!("{:?}", s); // Output: MyStruct { x: 10, y: 3.14 }}

Clone: ​​A deep copy method for generating types.

#[derive(Clone)]
struct MyStruct {
    x: i32,
    y: String,
}

fn main() {
    let s1 = MyStruct { x: 42, y: "Hello".to_string() };
    let s2 = ();
    println!("s1: {:?}, s2: {:?}", s1, s2);
}

Copy: Indicates that the type supports copy by value (usually used with Clone).

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p1 = Point { x: 0, y: 0 };
    let p2 = p1; // It will not be moved, copy it directly    println!("{:?}, {:?}", p1, p2);
}

Note: It can only be used for all fields that implement Copy types.

PartialEq and Eq: Implement comparison characteristics for type equality check.

#[derive(PartialEq, Eq)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 1, y: 2 };
    println!("{}", p1 == p2); // Output: true}

PartialOrd and Ord: Implement the sorting feature of types for comparison or sorting.

#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 2, y: 3 };
    println!("{}", p1 < p2); // Output: true}

Default: Generate default values ​​for types.

#[derive(Default)]
struct Config {
    port: u16,
    host: String,
}

fn main() {
    let default_config: Config = Default::default();
    println!("Port: {}, Host: {}", default_config.port, default_config.host);
}

Hash: Implements the hash feature, which is used as a key of a hash table.

use std::collections::HashSet;

#[derive(Hash, Eq, PartialEq, Debug)]
struct User {
    id: u32,
    name: String,
}

fn main() {
    let mut users = HashSet::new();
    (User { id: 1, name: "Alice".to_string() });
    (User { id: 2, name: "Bob".to_string() });
    println!("{:?}", users);
}

Combination use

#[derive(Debug, Clone, PartialEq)]
struct MyStruct {
    x: i32,
    y: String,
}

fn main() {
    let s1 = MyStruct { x: 10, y: "Rust".to_string() };
    let s2 = ();
    println!("{:?}", s1 == s2); // Output: true    println!("{:?}", s2);       // Output: MyStruct { x: 10, y: "Rust" }}

Things to note

  • Field requirements: Some features (such as Copy) require that all fields implement corresponding features.
  • Custom implementation: If the default behavior of #[derive] does not meet the requirements, the corresponding features can be implemented manually.
  • Dynamic logic is not supported: #[derive] is only applicable to static logic, and needs to be implemented manually if complex behavior is required.

#[derive] is a highly productive tool in the Rust type system, and through its powerful automation, developers can focus on business logic rather than duplicate code.

This is the article about how to use the #[derive] attribute in Rust. For more related Rust derive content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!