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
-
读写锁 类似于Mutex和RefCell
-
多个.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)