IT评测·应用市场-qidao123.com

标题: Rust编程语言入门之高级特性 [打印本页]

作者: 勿忘初心做自己    时间: 2023-4-25 00:18
标题: Rust编程语言入门之高级特性
高级特性

主要内容

一、不安全 Rust

匹配命名变量

Unsafe 超能力

解引用原始指针

解引用原始指针
  1. fn main() {
  2.   let mut num = 5;
  3.   
  4.   let r1 = &num as *const i32;
  5.   let r2 = &mut num as *mut i32;
  6.   unsafe {
  7.     println!("r1: {}", *r1);
  8.     println!("r2: {}", *r2);
  9.   }
  10.   
  11.   let address = 0x012345usize;
  12.   let r = address as *const i32;
  13.   unsafe {
  14.     println!("r: {}", *r); // 报错 非法访问
  15.   }
  16. }
复制代码
调用 unsafe 函数或方法

  1. unsafe fn dangerous() {}
  2. fn main() {
  3.   unsafe {
  4.     dangerous();
  5.   }
  6. }
复制代码
创建 Unsafe 代码的安全抽象

  1. fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
  2.   let len = slice.len();
  3.   
  4.   assert!(mid <= len);
  5.   
  6.   (&mut slice[..mid], &mut slice[mid..]) // 报错 cannot borrow `*slice` as mutable more than once at a time
  7. }
  8. fn main() {
  9.   let mut v = vec![1, 2, 3, 4, 5, 6];
  10.   
  11.   let r = &mut v[..];
  12.   let (a, b) = r.split_at_mut(3);
  13.   assert_eq!(a, &mut [1, 2, 3]);
  14.   assert_eq!(b, &mut [4, 5, 6]);
  15. }
复制代码
从其它语言调用 Rust 函数

  1. use std::slice;
  2. fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
  3.   let len = slice.len();
  4.   let ptr = slice.as_mut_ptr()
  5.   
  6.   assert!(mid <= len);
  7.   
  8.   unsafe {
  9.     (
  10.       slice::from_raw_parts_mut(ptr, mid),
  11.       slice::from_raw_parts_mut(ptr.add(mid), len = mid),
  12.     )
  13.   }
  14. }
  15. fn main() {
  16.   let address = 0x012345usize;
  17.   let r = address as *mut i32;
  18.   
  19.   let slice: &[i32] = unsafe {
  20.     slice::from_raw_parts_mut(r, 10000)
  21.   };
  22. }
复制代码
访问或修改一个可变静态变量

  1. extern "C" {
  2.   fn abs(input: i32) -> i32;
  3. }
  4. fn main() {
  5.   unsafe {
  6.     println!("Absolute value of -3 according to C: {}", abs(-3));
  7.   }
  8. }
复制代码
静态变量

常量和不可变静态变量的区别

  1. #[no_mangle]
  2. pub extern "C" fn call_from_c() {
  3.   println!("Just called a Rust function from C!");
  4. }
  5. fn main() {}
复制代码
实现不安全(unsafe)trait

  1. static HELLO_WORLD: &str = "Hello, world!";
  2. fn main() {
  3.   println!("name is: {}", HELLO_WORLD);
  4. }
复制代码
何时使用 unsafe 代码

二、高级 Trait

在 Trait 定义中使用关联类型来指定占位类型

  1. static mut COUNTER: u32 = 0;
  2. fn add_to_count(inc: u32) {
  3.   unsafe {
  4.     COUNTER += inc;
  5.   }
  6. }
  7. fn main() {
  8.   add_to_count(3);
  9.   
  10.   unsafe {
  11.     println!("COUNTER: {}", COUNTER);
  12.   }
  13. }
复制代码
关联类型与泛型的区别

泛型关联类型每次实现 Trait 时标注类型无需标注类型可以为一个类型多次实现某个 Trait(不同的泛型参数)无法为单个类型多次实现某个 Trait例子:
  1. unsafe trait Foo {
  2.   // methods go here
  3. }
  4. unsafe impl Foo for i32 {
  5.   // method implementations go here
  6. }
  7. fn main() {}
复制代码
默认泛型参数和运算符重载

例子一:
  1. pub trait Iterator {
  2.   type Item;
  3.   
  4.   fn next(&mut self) -> Option<Self::Item>;
  5. }
  6. fn main() {
  7.   println!("Hello, world!");
  8. }
复制代码
例子二:
  1. pub trait Iterator {
  2.   type Item;
  3.   
  4.   fn next(&mut self) -> Option<Self::Item>;
  5. }
  6. pub trait Iterator2<T> {
  7.   fn next(&mut self) -> Option<T>;
  8. }
  9. struct Counter {}
  10. impl Iterator for Counter {
  11.   type Item = u32;
  12.   
  13.   fn next(&mut self) -> Option<Self::Item> {
  14.     None
  15.   }
  16. }
  17. impl Iterator2<String> for Counter {
  18.   fn next(&mut self) -> Option<String> {
  19.     None
  20.   }
  21. }
  22. impl Iterator2<u32> for Counter {
  23.   fn next(&mut self) -> Option<u32> {
  24.     None
  25.   }
  26. }
  27. fn main() {
  28.   println!("Hello, world!");
  29. }
复制代码
默认泛型参数的主要应用场景

完全限定语法(Fully Qualified Syntax)如何调用同名方法

例子一:
  1. use std::ops::Add;
  2. #[derive(Debug, PartialEq)]
  3. struct Point {
  4.   x: i32,
  5.   y: i32,
  6. }
  7. impl Add for Point {
  8.   type Output = Point;
  9.   
  10.   fn add(self, other: Point) -> Point {
  11.     Point {
  12.       x: self.x + other.x,
  13.       y: self.y + other.y,
  14.     }
  15.   }
  16. }
  17. fn main() {
  18.   assert_eq!(Point {x: 1, y: 0} + Point {x: 2, y: 3},
  19.     Point {x: 3, y: 3}
  20.   );
  21. }
复制代码
例子二:
  1. use std::ops::Add;
  2. struct Millimeters(u32);
  3. struct Meters(u32);
  4. impl Add<Meters> for Millimeters {
  5.   type Output = Millimeters;
  6.   
  7.   fn add(self, other: Meters) -> Millimeters {
  8.     Millimeters(self.0 + (other.0 * 1000))
  9.   }
  10. }
  11. fn main() {
  12.   
  13. }
复制代码
完全限定语法(Fully Qualified Syntax)如何调用同名方法

  1. trait Pilot {
  2.   fn fly(&self);
  3. }
  4. trait Wizard {
  5.   fn fly(&self);
  6. }
  7. struct Human;
  8. impl Pilot for Human {
  9.   fn fly(&self) {
  10.     println!("This is your captain speaking.");
  11.   }
  12. }
  13. impl Wizard for Human {
  14.   fn fly(&self) {
  15.     println!("Up!");
  16.   }
  17. }
  18. impl Human {
  19.   fn fly(&self) {
  20.     println!("*waving arms furiously*");
  21.   }
  22. }
  23. fn main() {
  24.   let persion = Human;
  25.   person.fly(); // Human 本身的 fly 方法
  26.   Pilot::fly(&person);
  27.   Wizard::fly(&person);
  28. }
复制代码
使用 supertrait 来要求 trait 附带其它 trait 的功能

  1. trait Animal {
  2.   fn baby_name() -> String;
  3. }
  4. struct Dog;
  5. impl Dog {
  6.   fn baby_name() -> String {
  7.     String::from("Spot")
  8.   }
  9. }
  10. impl Animal for Dog {
  11.   fn baby_name() -> String {
  12.     String::from("puppy")
  13.   }
  14. }
  15. fn main() {
  16.   println!("A baby dog is called a {}", Dog::baby_name()); // Dog 本身的关联方法
  17. }
复制代码
使用 newtype 模式在外部类型上实现外部 trait

  1. trait Animal {
  2.   fn baby_name() -> String;
  3. }
  4. struct Dog;
  5. impl Dog {
  6.   fn baby_name() -> String {
  7.     String::from("Spot")
  8.   }
  9. }
  10. impl Animal for Dog {
  11.   fn baby_name() -> String {
  12.     String::from("puppy")
  13.   }
  14. }
  15. fn main() {
  16.   println!("A baby dog is called a {}", Dog::baby_name()); // Dog 本身的关联方法
  17.   println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
  18. }
复制代码
三、高级类型

使用 newtype 模式实现类型安全和抽象

使用类型别名创建类型同义词

例子一:
  1. use std::fmt;
  2. trait OutlinePrint: fmt::Display {
  3.   fn outline_print(&self) {
  4.     let output = self.to_string();
  5.     let len = output.len();
  6.     println!("{}", "*".repeat(len + 4));
  7.     println!("*{}*", " ".repeat(len + 2));
  8.     println!("* {} *", output);
  9.     println!("*{}*", " ".repeat(len + 2));
  10.     println!("{}", "*".repeat(len + 4));
  11.   }
  12. }
  13. struct Point {
  14.   x: i32,
  15.   y: i32,
  16. }
  17. impl OutlinePrint for Point {}
  18. impl fmt::Display for Point {
  19.   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  20.     write!(f, "({}, {})", self.x, self.y)
  21.   }
  22. }
  23. fn main() {}
复制代码
例子二:
  1. use std::fmt;
  2. struct Wrapper(Vec<String>);
  3. impl fmt::Display for Wrapper {
  4.   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  5.     write!(f, "[{}]", self.0.join(", "))
  6.   }
  7. }
  8. fn main() {
  9.   let w = Wrapper(vec![String::from("hello"), String::from("world")]);
  10.   println!("w = {}", w);
  11. }
复制代码
例子三:
  1. type Kilometers = i32;
  2. fn main() {
  3.   let x: i32 = 5;
  4.   let y: Killometers = 5;
  5.   println!("x + y = {}", x + y);
  6. }
复制代码
修改之后:
  1. fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
  2.   // --snip--
  3. }
  4. fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
  5.   Box::new(|| println!("hi"))
  6. }
  7. fn main() {
  8.   let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
  9. }
复制代码
Never 类型

例子一:
  1. type Thunk = Box<dyn Fn() + Send + 'static>;
  2. fn takes_long_type(f: Thunk) {
  3.   // --snip--
  4. }
  5. fn returns_long_type() -> Thunk {
  6.   Box::new(|| println!("hi"))
  7. }
  8. fn main() {
  9.   let f: Thunk = Box::new(|| println!("hi"));
  10. }
复制代码
例子二:
  1. use std::io::Error;
  2. use std::fmt;
  3. pub trait Write {
  4.   fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
  5.   fn flush(&mut self) -> Result<(), Error>;
  6.   
  7.   fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
  8.   fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Error>;
  9. }
  10. fn main() {
  11.   
  12. }
复制代码
注意:never 类型的表达式可以被强制的转化为任意其它类型
例子三:
  1. use std::fmt;
  2. // type Result<T> = Result<T, std::io::Error>; // 声明在 std::io 中
  3. type Result<T> = std::io::Result<T>;
  4. pub trait Write {
  5.   fn write(&mut self, buf: &[u8]) -> Result<usize>;
  6.   fn flush(&mut self) -> Result<()>;
  7.   
  8.   fn write_all(&mut self, buf: &[u8]) -> Result<()>;
  9.   fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()>;
  10. }
  11. fn main() {
  12.   
  13. }
复制代码
例子四:
  1. fn bar() -> ! { // 报错 返回单元类型 不匹配
  2.   
  3. }
  4. fn main() {}
复制代码
动态大小和 Sized Trait

Rust使用动态大小类型的通用方式

另外一种动态大小的类型:trait

Sized trait

  1. fn main() {
  2.   let guess = "";
  3.   
  4.   loop {
  5.     let guess: u32 = match guess.trim().parse() {
  6.       Ok(num) => num,
  7.       Err(_) => continue, // ! never 类型
  8.     };
  9.   }
  10. }
复制代码
?Sized trait 约束
  1. impl<T> Option<T> {
  2.   pub fn unwrap(self) -> T {
  3.     match self {
  4.       Some(val) => val,
  5.       None => panic!("called `Option::unwrap()` on a `None` value"), // !
  6.     }
  7.   }
  8. }
复制代码
四、高级函数和闭包

函数指针

  1. fn main() {
  2.   println!("forever");
  3.   
  4.   loop {
  5.     println!("and ever");
  6.   }
  7. }
复制代码
函数指针与闭包的不同

例子一
  1. fn generic<T>(t: T) {}
  2. fn generic<T: Sized>(t: T) {} // 上面的generic 会隐式的转化为这种
  3. fn main() {}
复制代码
例子二
  1. fn generic<T>(t: T) {}
  2. fn generic<T: Sized>(t: T) {}
  3. fn generic<T: ?Sized>(t: &T) {} // ? 只能用在 sized上
  4. fn main() {}
复制代码
返回闭包

  1. fn add_one(x: i32) -> i32 {
  2.   x + 1
  3. }
  4. fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
  5.   f(arg) + f(arg)
  6. }
  7. fn main() {
  8.   let answer = do_twice(add_one, 5);
  9.   
  10.   println!("The answer is: {}", answer);
  11. }
复制代码
五、宏

宏 macro

函数与宏的差别

macro_rules! 声明宏(弃用)

  1. fn main() {
  2.   let list_of_numbers = vec![1, 2, 3];
  3.   let list_of_strings: Vec<String> = list_of_numbers
  4.   .iter().map(|i| i.to_string()).collect();
  5.   
  6.   let list_of_numbers = vec![1, 2, 3];
  7.   let list_of_strings: Vec<String> = list_of_numbers
  8.   .iter().map(ToString::to_string).collect();
  9. }
复制代码
基于属性来生成代码的过程宏

  1. fn main() {
  2.   enum Status {
  3.     Value(u32),
  4.     Stop,
  5.   }
  6.   
  7.   let v = Status::Value(3);
  8.   
  9.   let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
  10. }
复制代码
自定义 derive 宏

[code]➜ cd rust~/rust➜ cargo new hello_macro --lib     Created library `hello_macro` package~/rust➜ cd hello_macrohello_macro on  master [?] via
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4