SoFunction
Updated on 2025-04-11

Detailed explanation of the use of generics in Rust

Generics are programming techniques that do not specify specific types when writing code, but then determine types when using them. It allows us to write more general and reusable code and avoid repeating similar code.

In Rust, generics are widely used in data types, functions and methods, trait and other aspects. This article will introduce in detail the related concepts and usage of generics in Rust.

Generic data types

When defining structures or enumerations, we can use generic parameters instead of specific types. This way, when using these structures or enums, we can specify specific types for them.

For example, the following is a defined using generic parametersPointStructure:

struct Point<T> {
    x: T,
    y: T,
}
let int_point = Point { x: 1, y: 2 };
let float_point = Point { x: 1.0, y: 2.0 };

In the above code, we define a name calledPointThe structure of  , which has two generic parametersxandy. When using this structure, we can specify a specific type for it, such asint_pointandfloat_pointShown.

Generic functions and methods

When defining a function or method, we can also use generic parameters instead of specific types. In this way, when calling these functions or methods, we can specify specific types for them.

For example, the following is a defined using generic parameterslargestFunction:

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    for &item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}
let numbers = vec![1, 2, 3];
let result = largest(&numbers);

In the above code, we define a name calledlargestThe function that accepts a generic parameterT. When calling this function, we can specify a specific type for it, such asresultShown.

Generic trait

When defining trait, we can also use generic parameters instead of specific types. In this way, when implementing these traits, we can specify specific types for them.

For example, the following is a defined using generic parametersSummary trait:

pub trait Summary {
    fn summarize<T: Display>(&self, value: T) -> String;
}
impl Summary for NewsArticle {
    fn summarize<T: Display>(&self, value: T) -> String {
        format!("{} - {}", , value)
    }
}

In the above code, we define a name calledSummarytrait, it has a generic methodsummarize. When implementing this trait, we can specify a specific type for it, such asNewsArticleShown.

Generic constraints

Sometimes, we need to impose some constraints on generic parameters to ensure that they meet certain conditions. In Rust, we can use the trait bound and where clauses to constrain generic parameters.

For example, thelargestIn the function, we use generic parametersTThe following constraints are implemented:

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    // ...
}

In the above code<T: PartialOrd + Copy>Partial representation: generic parametersTNeed to be implementedPartialOrdandCopyThese two traits. In this way, when calling this function, we can only pass in types that implement these two traits.

In addition to using trait bound, we can also use the where clause to constrain generic parameters. For example, the abovelargestFunctions can also be written like this:

fn largest<T>(list: &[T]) -> T
where
    T: PartialOrd + Copy,
{
    // ...
}

In the above codewhere T: PartialOrd + CopyPartial representation: generic parametersTNeed to be implementedPartialOrdandCopyThese two traits. This writing method is the same as using trait bound, except that the syntax is different. from Liu Jin, please indicate the original link when reprinting. grateful!

This is the end of this article about the detailed explanation of the use of generics in Rust. For more related Rust generic content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!