Rust高级学习
Rust 进阶学习笔记
泛型
trait
1ub struct Student {
2 pub name: String,
3 pub age: u32,
4}
5
6pub struct Teacher {
7 pub name: String,
8 pub age: u32,
9 pub subject: String,
10}
11
12pub trait GetInformation {
13 fn get_name(&self) -> &String;
14 fn get_age(&self) -> u32;
15}
16
17pub trait GetSubject {
18 fn get_subject(&self) -> &String;
19}
20
21trait SchoolName {
22 fn get_school_name(&self) -> String {
23 String::from("少年军校")
24 }
25}
26
27impl GetInformation for Student {
28 fn get_name(&self) -> &String {
29 &self.name
30 }
31 fn get_age(&self) -> u32 {
32 self.age
33 }
34}
35impl SchoolName for Student {}
36
37impl GetInformation for Teacher {
38 fn get_name(&self) -> &String {
39 &self.name
40 }
41 fn get_age(&self) -> u32 {
42 self.age
43 }
44}
45
46impl SchoolName for Teacher {
47 // override
48 fn get_school_name(&self) -> String {
49 String::from("一中")
50 }
51}
52
53impl GetSubject for Teacher {
54 fn get_subject(&self) -> &String {
55 &self.subject
56 }
57}
58
59// 第一种写法
60// trait bound 写法
61// t: &T 引用,否则会发生move
62fn show<T>(t: &T)
63 where T: GetInformation
64{
65 println!("item name: {}, age: {}", t.get_name(), t.get_age());
66}
67
68// 第二种写法
69fn show2<T: GetInformation> (t: &T) {
70 println!("item name: {}, age: {}", t.get_name(), t.get_age());
71}
72
73// 直接作为参数的写法
74fn print(item: impl GetInformation) {
75 println!("item name: {}, age: {}", item.get_name(), item.get_age());
76}
77
78fn create_student() -> impl GetInformation {
79 let s = Student{
80 name: String::from("小红"),
81 age: 14,
82 };
83 s
84 // 不能 使用if 判断 动态的生成Student 或者 Teacher 只能使用一种
85}
86
87fn main() {
88 let s = Student{
89 name: String::from("小明"),
90 age: 15,
91 };
92
93 let t = Teacher{
94 name: String::from("高老师"),
95 age: 30,
96 subject: String::from("语文"),
97 };
98
99 println!("student name: {}, age: {}, school name: {}", s.get_name(), s.get_age(), s.get_school_name());
100 println!("teacher name: {}, age: {}, subject: {}, school name: {}", t.get_name(), t.get_age(), t.get_subject(), t.get_school_name());
101 show(&s);
102 show(&t);
103 show2(&s);
104 show2(&t);
105 // 最后调用 s t 发生 move
106 print(s);
107 print(t);
108
109 let n = create_student();
110 show(&n);
111}
生命周期
1三条消除规则
2编译器使用三条消除规则来确定哪些场景不需要显式地去标注生命周期。其中第一条规则应用在输入生命周期上,第二、三条应用在输出生命周期上。若编译器发现三条规则都不适用时,就会报错,提示你需要手动标注生命周期。
3
41. 每一个引用参数都会获得独自的生命周期
5 例如一个引用参数的函数就有一个生命周期标注: fn foo<'a>(x: &'a i32),两个引用参数的有两个生命周期标注:fn foo<'a, 'b>(x: &'a i32, y: &'b i32), 依此类推。
62. 若只有一个输入生命周期(函数参数中只有一个引用类型),那么该生命周期会被赋给所有的输出生命周期,也就是所有返回值的生命周期都等于该输入生命周期
7 例如函数 fn foo(x: &i32) -> &i32,x 参数的生命周期会被自动赋给返回值 &i32,因此该函数等同于 fn foo<'a>(x: &'a i32) -> &'a i32
83. 若存在多个输入生命周期,且其中一个是 &self 或 &mut self,则 &self 的生命周期被赋给所有的输出生命周期
9拥有 &self 形式的参数,说明该函数是一个 方法,该规则让方法的使用便利度大幅提升。
1// 函数中的生命周期
2// error:
3// fn login(username: &str, password: &str) -> &str {
4// ^ expected named lifetime parameter
5// fix:
6fn login<'a>(username: &'a str, password: &'a str) -> &'a str {
7 if username == "admin" && password == "123456" {
8 &"8dbd2533-e13e-34d1-3594-149c115160f3"
9 } else {
10 &""
11 }
12}
13
14fn get_str<'a> (x: &'a str, _y: &'a str) -> &'a str {
15// y not used 可以去掉 'a
16// fn get_str<'a> (x: &'a str, y: &str) -> &'a str {
17 x
18}
19
20fn new_str<'a>(x: &'a str, y: &'a str) -> &'a str {
21// fn new_str(x: &str, y: &str) -> &str { // error
22 let r = String::from("guest");
23
24 // r.clone().as_str() error
25 // r.as_str() // drop 发生悬垂引用了
26 &"guest" // success
27}
28
29// 结构体中的生命周期
30#[derive(Debug)]
31struct User<'a> {
32 name: &'a str,
33}
34
35impl <'b> User<'b> {
36 fn get_user_id(&self) -> u32 {
37 1
38 }
39
40 fn get_user_name(&self, nick: &str) -> &str {
41 // 编译器会自动推到如下声明周期
42 // fn get_user_name<'b>(&'b self, nick: &str) -> &'b str {
43 self.name
44 }
45
46 // fn get_user_nick_with_name(&self, nick: &str) -> &str { // error
47 fn get_user_nick_with_name<'c>(&self, nick: &'c str) -> &'c str {
48 nick
49 }
50}
51
52// 静态生命周期, 存活整个程序期间, 所有字面字符串都是静态生命周期
53// let s: &'static str = "hello";
54
55fn main() {
56 let name = String::from("admin");
57 let u = User {
58 name: &name,
59 };
60 let pwd = String::from("123456");
61 let token = login(&name, &pwd);
62 println!("login user: {}, password: {}, token: {}", name, pwd, token);
63 println!("user: {:#?}", u);
64
65 let s = get_str(name.as_str(), pwd.as_str());
66 println!("s value: {:#?}", s);
67
68 let v = "root";
69 println!("v value: {:#?}", v);
70}
Closure闭包
1fn main() {
2 let use_closure = |v:i32| {
3 println!("this is a closure, v: {}", v);
4 };
5 use_closure(1);
6
7 // 闭包定义会为每个参数和返回值类型推导一个具体的类型,但是不能推导2次
8 // 声明的闭包函数 需要调用一次,推导具体的类型,不调用 编译不通过
9 let add_v2 = |x| x;
10 let first = add_v2(1);
11 println!("this is a closure, first: {}", first);
12 // 不能推导2次
13 // let second = add_v2(String::from("admin"));
14 // println!("this is a closure, second: {}", second);
15
16 let add_v3 = |y| {y+1};
17 add_v3(1);
18 let add_v4 = |n:i32|->i32 { n + 1 };
19 add_v4(4);
20
21 let i = 2;
22 let exe = |x| x + i;
23
24 // 在闭包捕获环境中的变量
25 let r = exe(5);
26 println!("this is a closure, r: {}", r);
27}
评论