Rust 知识积累(6)
-
impl Trait
-
使用(与泛型类似)
// 入参 举例 // 类似与 fn prints_it<T:String+std::fmt::Display>>(input: T){} fn prints_it(input: impl Into<String> + std::fmt::Display){ // 直接输出入参 println!("{}", input); } fn main(){ // c_str prints_it("hi"); // String prints_it(String::from("Hi")); }
-
-
闭包
在我理解。。。类似于反射的声明,然后在这个声明中调用该类的方法,期间该方法与其他代码相互独立
// 使用impl声明一个闭包 FnMut(i32) 得到的就是number fn returns_closure(input: &st)->impl FnMut(i32)->i32{ match input{ // 判断input是否为double,如果是则传入的number加2 "double" => |mut number|{ number += 2; number } } } fn main(){ // 调用 let mut doubles = returns_closure("double"); doubles(10); }
-
Arc 原子引用计数器
线程或同时运算时保持原子性的类型
// 引用Arc和Mutex包 use std::sync::{Arc, Mutex}; fn main(){ // 声明原子计数 let my_number = Arc::new(Mutex::new(0)); // 声明一个数组 let mut handle_vec = Vec![]; // 从0开始循环 for _ in 0..2{ let my_number = Arc::Clone(&my_number); let handle = std::thread::spawn(move || { for _ in 0..10{ *my_number.lock().unwrap() += 1; } }); handle_vec.push(handle); } handle_vec.into_iter().for_each(|handle| handle.join().unwrap()); // 结果为20 println!("{:?}", my_number); }
-
Channels
通道,类似于socket连接时,一个是发送端,一个是接收端一样
// 生产者和消费者需要绑定在一起 pub fn channel<T>()->(Sender<T>, Recever<T>) // 声明 use std::sync::mpsc::{channel, Sender, Receiver}; let (s, r):(Sender<i32>, Receiver<i32>) = channel(); // 简写 use std::sync::mpsc::channel; let (sender, receiver) = channel(); sender.send(5); receiver.recv(); //线程中使用 use std::sync::mpsc::channel; fn main() { let (sender, receiver) = channel(); let sender_clone = sender.clone(); // 使用线程向管道中发送一条信息 std::thread::spawn(move|| { sender.send("Send a &str this time").unwrap(); }); // 通过克隆的参数向管道中发送一条信息 std::thread::spawn(move|| { sender_clone.send("And here is another &str").unwrap(); }); // 打印接收内容内容 println!("{:?}", receiver.recv().unwrap()); // 如何同时打印两个信息 // 使用 let mut handle_vec = vec![];保存线程返回变量 // for _ in handle_vec{} // 遍历中使用receiver.recv().unwarp();可同时显示两个 }
属性
以'# []'或'# ![]'声明的 例如:
'# [derive(Debug)]' 影响下一行代码
'# ![derive(Debug)]' 将影响整个空间
-
写了没有使用的代码,仍然会编译
// #[allow(dead_code)] 和 #[allow(unused_variables)] // struct 只是声明,没有使用 #![allow(dead_code)] #![allow(unused_variables)] // 声明了很多不同的struct struct Struct1 {} struct Struct2 {} struct Struct3 {} struct Struct4 {} struct Struct5 {} fn main() { // 声明了四个变量,编译器不会进行任何操作 let char1 = 'ん'; let char2 = ';'; let some_str = "I'm just a regular &str"; let some_vec = vec!["I", "am", "just", "a", "vec"]; }
-
创建结构和枚举派生
// 该声明以后,HoldsAString都可以使用 #[derive(Debug)] struct HoldsAString { the_string: String, } fn main() { let my_string = HoldsAString { the_string: "Here I am!".to_string(), }; // 结果为:Here I am! println!("{:?}", my_string); }
-
配置
'#[cfg()]'的意思是配置 ,例如
'# [cfg(test)] ' // 告诉编译器不要运行他们,除非是在测试
'# [cfg(target_os = "windows")] ' // windows环境下运行
'# ![no_std]' // 不要引入std的标准库
Box
使用Box时,可以把一个类型放在堆上而不是栈上
可以将它作为智能指针使用
//1 let my_box = Box::new(1); // This is Box<i32> let an_integer = *my_box; // this is i32 //2 struct List{ item: Option<Box<List>>,} impl List{ fn new() -> List{ List{ item: Som(Box::new(List{item: None})), } } } fn main(){ let mut my_list = List::new(); }
-
Box包裹trait
use std::error::Error; use std::fmt; #[derive(Debug)] struct ErrorOne; // Error带有Debug类型 impl Error for ErrorOne {} // ErrorOne中重写了fmt方法 impl fmt::Display for ErrorOne { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // 向自身写入You got the first error!字符串 write!(f, "You got the first error!") } } // 与ErrorOne类似 #[derive(Debug)] struct ErrorTwo; impl Error for ErrorTwo {} impl fmt::Display for ErrorTwo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "You got the second error!") } } // 声明一个调用方法 fn returns_errors(input: u8) -> Result<String, Box<dyn Error>> { match input { // 注意 将ErrorOne和ErrorTwo都进行了装盒 0 => Err(Box::new(ErrorOne)), 1 => Err(Box::new(ErrorTwo)), // 当成功的时候返回该字符串 _ => Ok("Looks fine to me".to_string()), } } fn main() { // 声明了一个数组,并存储了三个数值 let vec_of_u8s = vec![0_u8, 1, 80]; for number in vec_of_u8s { // 循环数组,根据不同的数值返回不同的结果 match returns_errors(number) { Ok(input) => println!("{}", input), Err(message) => println!("{}", message), } } }
默认值
-
Default::default()
// 主要使用 let default_i8 : i8 = Default::default(); // 0 let default_str : String = Default::default(); // "" let default_bool : bool = Default::default(); // false // struct默认值 #[derive(Debug)] struct Character { name: String, age: u8, height: u32, weight: u32, lifestate: LifeState, } #[derive(Debug)] enum LifeState { Alive, Dead, NeverAlive, Uncertain, } impl Character { fn new(name: String, age: u8, height: u32, weight: u32, alive: bool) -> Self { Self { name, age, height, weight, lifestate: if alive { LifeState::Alive } else { LifeState::Dead }, } } } impl Default for Character { fn default() -> Self { Self { name: "Billy".to_string(), age: 15, height: 170, weight: 70, lifestate: LifeState::Alive, } } } fn main() { let character_1 = Character::default(); println!( "The character {:?} is {:?} years old.", character_1.name, character_1.age ); }
建造者模式
// 注意 mut self而不是&mut self
// 改变自身的height,并返回自身
fn height(mut self, height: u32) -> Self {
self.height = height;
self
}
// 调用Character::default().height(180)
Deref和DerefMut
-
通过实现Deref,可以将智能指针视作常规引用来进行处理。
use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; // 类型标注后边会有介绍,可先忽略 fn deref(&self) -> &T { // 返回成员的引用 &self.0 } } assert_eq!(5, *y); // 事实上*y会被编译成 *(y.deref())
-
使用new实例化,等返回self时只会返回Deref中的设置信息
use std::ops::Deref; #[derie(Debug)] struct HoldsANumber(u8); impl Deref for HoldsANumber{ type Target = u8; fn deref(&self)->&Self::Target{ &self.0 } } let my_num = HoldsANUmber(20); println!("{:?}", *my_num + 20) // 标准库实例 use std::ops::Deref; struct DerefExample<T>{ value:T } impl<T> Deref for DerefExample<T>{ type Target = T; fn deref(&self) -> &Self::Target{ &self.alue } } fn main(){ let x = DerefExample{ value:'a'}; assert_eq!('a', *x); }
-
checked_sub() 安全的减法,整数可直接使用,如果失败返回None,不会崩溃
-
DerefMut 与Deref使用基本一致,唯一的不同是有了Mut,意味着可修改,使用前必须引用和实现Deref
use std::ops::{Deref, DerefMut}; struct HoldsANumber(u8); impl HoldsANumber { fn prints_the_number_times_two(&self) { println!("{}", self.0 * 2); } } // 使用DerefMut之前必须先声明Deref impl Deref for HoldsANumber { type Target = u8; fn deref(&self) -> &Self::Target { &self.0 } } // 这个因为使用了Deref,因此不需要输入:Target = u8; impl DerefMut for HoldsANumber { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } fn main() { let mut my_number = HoldsANumber(20); *my_number = 30; println!("{:?}", my_number.checked_sub(100)); my_number.prints_the_number_times_two(); }
Create和模块
// 声明一个mod
mod print_things{
use std::fmt::Display;
//必须加pub
pub fn prints_one<T: Display>(input: T){
println!("{}", input);
}
}
fn main(){
use create::print_thines::prints_one;
prints_one(6);
}