- 定义:类型是对数据的分类,这个分类定义了这些数据的意义、被允许的值的集合,还有能在这些数据上执⾏哪些操作。编译器或运⾏时会检查类型化过程,以确保数据的完整性,对数据施加访问限制,以及把数据按程序员的意图进⾏解释。类型对于变量来说,是⼀种约束。
 
泛型
- 在使用泛型时,完全不用担心性能上的问题,Rust是在编译期为泛型对应的多个类型,生成各自的代码,因此损失了编译速度和增大了最终生成文件的大小。
 
struct中的泛型
use std::fmt::Display;
// 对struct的泛型约束
// : Display表示T泛型只接受实现了Display的类型
#[derive(Debug)]
struct Number<T: Display> {
    a: T
}
#[derive(Debug)]
struct NumberTwo<T: Display, U: Display> {
    a: T,
    b: U
}
// 对struct的泛型约束T的公共实现方法content
impl<T: Display> Number<T> {
    fn content(&self) {
        println!("{}", self.a);
    }
}
// strcut Number<T>中的T是泛型定义参数T,impl<T> Number<T>中的Number<T>中的T是使用类型T,
// 是在impl后定义的,所以此处的A与上面的T是一样的效果,类似别名效果
impl<A: Display> Number<A> {
    fn same_content(&self) {
        println!("{}", self.a);
    }
}
// 只对struct的泛型约束u64的实现方法content64
impl Number<u64> {
    fn content64(&self) {
        println!("{}", self.a);
    }
}
fn main() {
    let number = Number{a: 12};
    println!("{:?}", number);
    // ::<u32>规定其实现类型
    let number = Number::<u32>{a:32};
    println!("{:?}", number);
    number.content();
    number.same_content();
    // number.content64(); // u32实现中并无此方法
    let number = Number::<u64>{a:32};
    number.content();
    number.content64();
    let number_two = NumberTwo::<u32, String>{a:32, b: "ohBug".to_string()};
    println!("{:?}", number_two)
}
//output
Number { a: 12 }
Number { a: 32 }
32
32
32
32
方法中的泛型
use std::fmt::Display;
// T 被泛型限制必须实现了Display
fn println<T: Display>(target: T) -> T{
    println!("{}", target);
    target
}
fn main() {
    let str = "ohBug";
    let result = println(str);
    println!("{}", result)
}
ohBug
ohBug
 
const泛型
- 之前的泛型都是对类型的规范,而const泛型可以做到对值的规范。
 
use std::fmt::{Debug, Display};
fn main() {
    let arr: [u32; 3] = [1, 2, 3];
    arr_one(&arr);
    // arr_two(&arr); 报错,因为类型是三个长度,但是方法参数是接受两个参数长度的u32数组
    arr_three(&arr);
    arr_four(&arr);
    arr_five(&arr);
}
fn arr_one(arr: &[u32; 3]) {
    println!("{:?}", arr)
}
fn arr_two(arr: &[u32; 2]) {
    println!("{:?}", arr)
}
// 只能接受u32类型的数组
fn arr_three(arr: &[u32]) {
    println!("{:?}", arr)
}
// 相较于上面,能接受任何实现了Debug的类型的数组
fn arr_four<T: Debug>(arr: &[T]) {
    println!("{:?}", arr)
}
// 相较于上面,虽然没有其灵活,但是更严谨
// 表示 const 泛型 N ,它基于的值类型是 usize
fn arr_five<T: Debug, const N: usize>(arr: &[T; N]) {
    println!("{:?}", arr)
}
//output
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
- 泛型还可以基于表达式,详见
nightly版本下#![feature(generic_const_exprs)] 。 
 
const fn
- 就是常量函数,
const fn 允许我们在编译期对函数进行求值,可以在编译期执行这些函数,从而将计算结果直接嵌入到生成的代码中。 
struct Buffer<const N: usize> {
    data: [u8; N],
}
const fn compute_buffer_size(factor: usize) -> usize {
    factor * 1024
}
fn main() {
    const SIZE: usize = compute_buffer_size(4);
    let buffer = Buffer::<SIZE> {
        data: [0; SIZE],
    };
    println!("Buffer size: {} bytes", buffer.data.len());
}
// output: Buffer size: 4096 bytes