一、泛型概念
泛型很多编程语言都会实现的特性。在处理数据结构的时候可以带来很大便利性。或者一些工具函数可以处理多种类型。
当然熟悉go的童鞋,可能要说,没有泛型也可以写数据结构啊。这涉及到反射和泛型的一些差别。泛型在性能上更占优势,
因为大部分语言在实现泛型都会选择特例化类型
1.rust泛型特例化
先给v_str初始化一些&str, 然后push一个int。看编译器报错
| 1
2
3
4
 | fn main() {
    let mut v_str = vec!["1123", "345"];
    v_str.push(1);
}
 | 
 
输出
| 1
2
3
4
5
6
7
8
 | error[E0308]: mismatched types
 --> src/main.rs:3:16
  |
3 |     v_str.push(1);
  |                ^ expected `&str`, found integer
error: aborting due to previous error
 | 
 
这里的v_str已经是&str类型,再push int就会报错。
所以特例化之后的泛型类型就是具体类型了。泛型不会带来抽象开销,所以效率还是很高的。
2.写法
函数名之后带<T>, 类型使用<T>里面的值。
二、实战-实现泛型max函数
1.先按感觉写
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
 | fn max<T>(a: T, b: T) -> T {
    if a < b {
        return b;
    }
    return a;
}
fn main() {
    println!("Hello, world!");
}
 | 
 
2.cargo build 看下输出
从报错上来看,编译器老师傅告诉我们出错原因,和建议。我们先按建议修改下。泛型类型要加下约束,实现了约束的类型可以使用这个max函数。
这个可以理解,编译器加强前置检查。能编译通过后面基本没啥问题。总比某个语言template报错,地球人都看不懂。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 | error[E0369]: binary operation `<` cannot be applied to type `T`
 --> src/main.rs:2:10
  |
2 |     if a < b {
  |        - ^ - T
  |        |
  |        T
  |
help: consider restricting type parameter `T`
  |
1 | fn max<T: std::cmp::PartialOrd>(a: T, b: T) -> T {
  |         ^^^^^^^^^^^^^^^^^^^^^^
 | 
 
3.修改之后的代码
运行成功
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 | fn max<T: std::cmp::PartialOrd>(a: T, b: T) -> T {
    if a < b {
        return b;
    }
    return a;
}
fn main() {
    println!("{}", max(1, 2));
    println!("{}", max(2.2, 1.1));
    println!("{}", max("hello", "h"));
}
// output:
//       2
//       2.2
//       hello
 | 
 
三、实战-实现泛型index函数
在golang有时候要使用index函数,如果是strings or bytes类型还好,标准库里面有,如果是int 就尴尬了。
也可以用reflect实现,就是速度慢点。当然有泛型的rust这点还是不错的。
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 | fn index<T: std::cmp::PartialEq>(a: &[T], b: T) -> i32 {
    for (i, item) in a.iter().enumerate() {
        if item == &b {
            return i as i32;
        }
    }
    return -1;
}
fn main() {
    println!("find index:{}", index(&vec![1, 2, 3, 4, 5,], 5));
    println!("find index:{}", index(&vec![1, 2, 3, 4, 5,], 6));
    println!("find index:{}", index(&vec!["hello", "world"], "world"));
    println!("find index:{}", index(&vec!["hello", "world"], "wo qu"));
}
// output
//       find index:4
//       find index:-1
//       find index:1
//       find index:-1
 |