Rust 知识积累

Posted 摧残一生 涅槃重生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust 知识积累相关的知识,希望对你有一定的参考价值。

&str

字符串
  • 直接声明时,生命周期为整个程序,直接写进了二进制中,类型为&\'static str\',意为字符串字元有一个叫static的生命期
借用str
  • 作为String的引用来使用,无生命期,例如 fn print_str(my_str: &str),调用为print_str(&String::format("string""));

生命期

  • 引用的生命期不能比这个对象长

    fn returns_str() -> &str
        return "I am" // ---错误,因为这个值声明是在方法内,引用出去后是null
    
    // 改进
    fn returns_str() -> &‘static str
        return "I am" // ---正确,返回了字符串字面量,该值整个程序有效
    
    

struct使用

  • 基础使用

    // 尝试写struct City<\'a>和name: &\'a str
    // 意思是 name可以存活到与City一样的生命期
    // a可以为任意值
    #[derive(Debug)]
    struct City<\'a>
        name: &\'a str,
        date_f: u32,
    
    let my_city = City
        name: &"China".to_string(),
        date_f: 2022,
    
    
  • 添加调用方法

    // 不仅仅struct要与name同一个生命期,impl也要一致
    struct Adventurer<\'a>
        name: &\'a str,
        hit_points: u32,
    
    impl Adventer<\'_>
        fn take_damage(&mut self)
            slef.hit_points -= 20;
            println!(" has  hit", slef.name, self.hit_points);
        
    
    fn main()
        let mut bi = Adventurer
            name:"Billy",
            hit_points: 100,
        
        bi.take_damage();
    
    

内部可变性

  • 不用mut也可修改数据,例如Cell,RefCell,Mutex, RwLock

  • Cell

    // 给出的是值而不是引用
    use std::cell::Cell;
    struct PhoneModel
        on_sale: Cell<bool>,
    
    fn main()
        let huawei_phone = PhoneModel
            on_sale: Cell::new(true),
        ;
        huawei_phone.on_sale.set(false);
    
    
  • RefCell

    // 引用单元格,引用
    // 小心使用,他是运行后编译
    use std::cell::RefCell;
    struce User
        active: RefCell<bool>,
    
    fn main()
        let user_l = user
            active: RefCell::new(true),
        ;
        println!("", user_l.active);
    
        user_l.active.borrow();
        user_l.active.borrow_mut(); //引出后就不能再borrow_mut()了
        user_l.active.replace(false);
    
    
    
  • Mutex

    线程安全,只让一个线程修改它(有lock())

    use std::sync::Mutex;
    let my_mutex = Mutex::new(5);
    // 加锁
    let mut mutex_changer = my_mutex.lock().unwarp();
    // 加锁后修改,也可大括号括起来,括号外自己解锁(超出加锁范围)
    *mutex_changer = 6;
    // 解锁
    std::mem::drop(mutex_changer);
    // 判断是否可用
    if let Ok(value) = my_mutex.try_lock()
        //没加锁
    else
        // 加锁
    
    
    // 直接赋值,不需要解锁
    *my_mutex.lock().unwarp() = 6;
    
  • RwLock

    1. 读写锁 类似于Mutex和RefCell

    2. 多个.read() 可以,一个.write() 可以

    use std::sync::RwLock;
    let my_rwlock = RwLock::new(5);
    let read1 = my_rwlock.read().unwrap(); // 多个read都可以
    let read2 = my_rwlock.read().unwrap();// 多个read都可以
    drop(read1); 
    drop(read2); // 两个read()都进行了解锁,因此可以write()
    let mut write1 = my_rwlock.write().unwarp();
    *write1 = 6;
    drop(write1); // 解锁后可继续操作
    
    if let Ok(mut number) = my_rwlock.try_write()
        *number += 10
    else
        // 锁住了
    
    

Cow

  • 枚举,写时克隆

    // 说明: 当类型为B时,返回 Borrowed(&\'a B), 否则 Owned(<B as ToOwned>:Owned)
    pub enum Cow<\'a, B> where B: \'a + ToOwned + ?Size,
        Borrowed(&\'a B),
        Owned(<B as ToOwned>:Owned),
    
    // Cow<\'static, str>判断时为
    // Cow::Borrowed(message) : message 为 实际值
    // Cow::Owned(message) : message 为 实际值
    //注意,返回的数值是str
    fn modulo_3(input: u8) -> Cow<\'static, str> 
        match input % 3 
            0 => "Remainder is 0".into(),
            1 => "Remainder is 1".into(),
            remainder => format!("Remainder is ", remainder).into(), // 这个为String,因此会变成Cow::Owned()
        
    
    
    fn main() 
        for number in 1..=6 
            match modulo_3(number) 
                Cow::Borrowed(message) => println!(" went in. The Cow is borrowed with this message: ", number, message),
                Cow::Owned(message) => println!(" went in. The Cow is owned with this message: ", number, message),
            
        
    
    

类型别名

  • 声明别名的几种方式及使用

    //方式一
    type CharacterVec = Vec<char>;
    //方式二
    type SkipFourTakeFive<\'a> = std::iter::Take<std::iter::Skip<std::slice::Iter<\'a, char>>>;
    fn returns<\'a>(input: &\'a Vec<char>) -> SkipFourTakeFive 
        input.iter().skip(4).take(5)
    
    //方式三
    use std::iter::Task, Skip;
    use std::slice::Iter;
    fn returns<\'a>(input: &\'a Vec<char>) -> Take<Skip<Iter<\'a, char>>> 
        input.iter().skip(4).take(5)
    
    //方式四
    struct File(String); // File is a wrapper around String
    
    fn main() 
        let my_file = File(String::from("I am file contents"));
        let my_string = String::from("I am file contents");
        println!("", my_file == my_string);  // ⚠️ 错误,不能比较,因为类型不对
        println!("", my_file.0 == my_string);//      正确
    
    //方式五 enum枚举简单调用
    enum MapDirection
        North, East,
    
    fn main()
        use MapDirection::*;
        //后面可直接使用 MapDirction
        match direction
            North => println!(),
            East => println!();
        
        // 也可以进行改名
        use MapDirection::
            North as N,
            East as E,
        
    
    

todo! 宏

  • 还未想好如何操作,但是又要运行,可以用 todo!()

    fn get_book(book: &Book) -> Option<String> 
        todo!() // todo means "I will do it later, please be quiet"
    
    

Rc

  • 使用数量变为0,才会消失

    use std::rc:Rc;
    let history = Rc::new("".to_string());
    let h2 = history.clone() // Rc的计数变为了2
    println!("", Rc::strong_count(&history)); //强引用数量
    Rc::downgrade(&item) 来创建弱引用 //如果只有弱引用,则变量会消失
    Rc::weak_count(&item) 查看弱引用数
    

多线程

  • std ::thread ::spawn 创建线程

    fn main()
        //当主程序结束,线程还未结束时,会报异常
        std::thread::spawn(||
            println!("");
        );
        // 改进 将线程绑定到变量上
        let handle = std::thread::spawn(||
            println!("");
        );
        handle.join();
        
        // 取值
        let mut my_str = String::form("");
        let handle = std::thread::spawn(move ||  // 使用move来获得线程外的数值
            println!("", my_str);
        );
        handle.join();
    
    

闭包

  • FnOnce: 取整个值

  • FnMut : 取一个可变引用

  • Fn : 取一个普通引用

  • 各种方式举例

    // fn方式
    let my_str = String::form("string");
    let my_closure = || println!("", my_str);
    my_closure();   //可多次调用    
    my_closure(); // String没有实现copy,因此是Fn
    
    // FnMut方式
    let mut my_str = String::form("string");
    let mut my_closure = || 
        my_str.push_str(" clone");
        println!("", my_str);
    
    my_closure();   //可多次调用,my_str会新增clone字符串
    my_closure();   // 如果改变my_str, 就变成了FnMut
    
    //  FnOnce方式
    let my_vec: Vec<i32> = vec![8, 9, 10];
    let my_closure = || 
        my_vec
        .into_iter() // into_iter takes ownership
        .map(|x| x as u8) // turn it into u8
        .map(|x| x * 2) // multiply by 2
        .collect::<Vec<u8>>() // collect into a Vec
    ;
    let new_vec = my_closure(); //只能使用一次
    

以上是关于Rust 知识积累的主要内容,如果未能解决你的问题,请参考以下文章

Rustlings:送给Rust初学者的知识点练习题集推荐(MacOSX)

用Rust语言开发Linux内核,得先过内存模型这关

用Rust语言开发Linux内核,得先过内存模型这关

刷完欧拉计划中难度系数为5%的所有63道题,我学会了Rust中的哪些知识点?

一起来学rust|简单的mingrep

java——网络知识积累