Rust 知识积累(6)

发布时间 2023-04-20 15:06:02作者: 摧残一生
  • 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);   
}