Rust高级特性主要内容不安全Rust高级Trait高级类型高级函数和闭包宏一、不安全Rust匹配命名变量隐藏着第二个语言,它没有强制内存安全保证:UnsafeRust(不安全的Rust)和普通的Rust一样,但提供了额外的“超能力”UnsafeR
fn main() {
  let mut num = 5;
  let r1 = &num as *const i32;
  let r2 = &mut num as *mut i32;
  unsafe {
    println!("r1: {}", *r1);
    println!("r2: {}", *r2);
  }
  let address = 0x012345usize;
  let r = address as *const i32;
  unsafe {
    println!("r: {}", *r); // 报错 非法访问
  }
}unsafe fn dangerous() {}
fn main() {
  unsafe {
    dangerous();
  }
}fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
  let len = slice.len();
  assert!(mid <= len);
  (&mut slice[..mid], &mut slice[mid..]) // 报错 cannot borrow `*slice` as mutable more than once at a time
}
fn main() {
  let mut v = vec![1, 2, 3, 4, 5, 6];
  let r = &mut v[..];
  let (a, b) = r.split_at_mut(3);
  assert_eq!(a, &mut [1, 2, 3]);
  assert_eq!(b, &mut [4, 5, 6]);
}修改之后:
use std::slice;
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
  let len = slice.len();
  let ptr = slice.as_mut_ptr()
  assert!(mid <= len);
  unsafe {
    (
      slice::from_raw_parts_mut(ptr, mid),
      slice::from_raw_parts_mut(ptr.add(mid), len = mid),
    )
  }
}
fn main() {
  let address = 0x012345usize;
  let r = address as *mut i32;
  let slice: &[i32] = unsafe {
    slice::from_raw_parts_mut(r, 10000)
  };
}extern "C" {
  fn abs(input: i32) -> i32;
}
fn main() {
  unsafe {
    println!("Absolute value of -3 according to C: {}", abs(-3));
  }
}#[no_mangle]注解:避免 Rust 在编译时改变它的名称#[no_mangle]
pub extern "C" fn call_from_c() {
  println!("Just called a Rust function from C!");
}
fn main() {}static HELLO_WORLD: &str = "Hello, world!";
fn main() {
  println!("name is: {}", HELLO_WORLD);
}static mut COUNTER: u32 = 0;
fn add_to_count(inc: u32) {
  unsafe {
    COUNTER += inc;
  }
}
fn main() {
  add_to_count(3);
  unsafe {
    println!("COUNTER: {}", COUNTER);
  }
}unsafe trait Foo {
  // methods go here
}
unsafe impl Foo for i32 {
  // method implementations go here
}
fn main() {}pub trait Iterator {
  type Item;
  fn next(&mut self) -> Option<Self::Item>;
}
fn main() {
  println!("Hello, world!");
}| 泛型 | 关联类型 | 
|---|---|
| 每次实现 Trait 时标注类型 | 无需标注类型 | 
| 可以为一个类型多次实现某个 Trait(不同的泛型参数) | 无法为单个类型多次实现某个 Trait | 
例子:
pub trait Iterator {
  type Item;
  fn next(&mut self) -> Option<Self::Item>;
}
pub trait Iterator2<T> {
  fn next(&mut self) -> Option<T>;
}
struct Counter {}
impl Iterator for Counter {
  type Item = u32;
  fn next(&mut self) -> Option<Self::Item> {
    None
  }
}
impl Iterator2<String> for Counter {
  fn next(&mut self) -> Option<String> {
    None
  }
}
impl Iterator2<u32> for Counter {
  fn next(&mut self) -> Option<u32> {
    None
  }
}
fn main() {
  println!("Hello, world!");
}<PlaceholderType=ConcreteType>例子一:
use std::ops::Add;
#[derive(Debug, PartialEq)]
struct Point {
  x: i32,
  y: i32,
}
impl Add for Point {
  type Output = Point;
  fn add(self, other: Point) -> Point {
    Point {
      x: self.x + other.x,
      y: self.y + other.y,
    }
  }
}
fn main() {
  assert_eq!(Point {x: 1, y: 0} + Point {x: 2, y: 3},
    Point {x: 3, y: 3}
  );
}例子二:
use std::ops::Add;
struct Millimeters(u32);
struct Meters(u32);
impl Add<Meters> for Millimeters {
  type Output = Millimeters;
  fn add(self, other: Meters) -> Millimeters {
    Millimeters(self.0 + (other.0 * 1000))
  }
}
fn main() {
}例子一:
trait Pilot {
  fn fly(&self);
}
trait Wizard {
  fn fly(&self);
}
struct Human;
impl Pilot for Human {
  fn fly(&self) {
    println!("This is your captain speaking.");
  }
}
impl Wizard for Human {
  fn fly(&self) {
    println!("Up!");
  }
}
impl Human {
  fn fly(&self) {
    println!("*waving arms furiously*");
  }
}
fn main() {
  let persion = Human;
  person.fly(); // Human 本身的 fly 方法
  Pilot::fly(&person);
  Wizard::fly(&person);
}例子二:
trait Animal {
  fn baby_name() -> String;
}
struct Dog;
impl Dog {
  fn baby_name() -> String {
    String::from("Spot")
  }
}
impl Animal for Dog {
  fn baby_name() -> String {
    String::from("puppy")
  }
}
fn main() {
  println!("A baby dog is called a {}", Dog::baby_name()); // Dog 本身的关联方法
}<Type as Trait>::function(receiver_if_method, netx_arg, ...);
trait Animal {
  fn baby_name() -> String;
}
struct Dog;
impl Dog {
  fn baby_name() -> String {
    String::from("Spot")
  }
}
impl Animal for Dog {
  fn baby_name() -> String {
    String::from("puppy")
  }
}
fn main() {
  println!("A baby dog is called a {}", Dog::baby_name()); // Dog 本身的关联方法
  println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
}use std::fmt;
trait OutlinePrint: fmt::Display {
  fn outline_print(&self) {
    let output = self.to_string();
    let len = output.len();
    println!("{}", "*".repeat(len + 4));
    println!("*{}*", " ".repeat(len + 2));
    println!("* {} *", output);
    println!("*{}*", " ".repeat(len + 2));
    println!("{}", "*".repeat(len + 4));
  }
}
struct Point {
  x: i32,
  y: i32,
}
impl OutlinePrint for Point {}
impl fmt::Display for Point {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "({}, {})", self.x, self.y)
  }
}
fn main() {}use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "[{}]", self.0.join(", "))
  }
}
fn main() {
  let w = Wrapper(vec![String::from("hello"), String::from("world")]);
  println!("w = {}", w);
}例子一:
type Kilometers = i32;
fn main() {
  let x: i32 = 5;
  let y: Killometers = 5;
  println!("x + y = {}", x + y);
}例子二:
fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
  // --snip--
}
fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
  Box::new(|| println!("hi"))
}
fn main() {
  let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
}修改之后:
type Thunk = Box<dyn Fn() + Send + 'static>;
fn takes_long_type(f: Thunk) {
  // --snip--
}
fn returns_long_type() -> Thunk {
  Box::new(|| println!("hi"))
}
fn main() {
  let f: Thunk = Box::new(|| println!("hi"));
}例子三:
use std::io::Error;
use std::fmt;
pub trait Write {
  fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
  fn flush(&mut self) -> Result<(), Error>;
  fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
  fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Error>;
}
fn main() {
}修改之后:
use std::fmt;
// type Result<T> = Result<T, std::io::Error>; // 声明在 std::io 中
type Result<T> = std::io::Result<T>;
pub trait Write {
  fn write(&mut self, buf: &[u8]) -> Result<usize>;
  fn flush(&mut self) -> Result<()>;
  fn write_all(&mut self, buf: &[u8]) -> Result<()>;
  fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<()>;
}
fn main() {
}例子一:
fn bar() -> ! { // 报错 返回单元类型 不匹配
}
fn main() {}例子二:
fn main() {
  let guess = "";
  loop {
    let guess: u32 = match guess.trim().parse() {
      Ok(num) => num,
      Err(_) => continue, // ! never 类型
    };
  }
}注意:never 类型的表达式可以被强制的转化为任意其它类型
例子三:
impl<T> Option<T> {
  pub fn unwrap(self) -> T {
    match self {
      Some(val) => val,
      None => panic!("called `Option::unwrap()` on a `None` value"), // !
    }
  }
}例子四:
fn main() {
  println!("forever");
  loop {
    println!("and ever");
  }
}let s1: str = "Hello there!";let s2: str = "How's it going?";fn generic<T>(t: T) {}
fn generic<T: Sized>(t: T) {} // 上面的generic 会隐式的转化为这种
fn main() {}fn generic<T>(t: T) {}
fn generic<T: Sized>(t: T) {} 
fn generic<T: ?Sized>(t: &T) {} // ? 只能用在 sized上
fn main() {}fn add_one(x: i32) -> i32 {
  x + 1
}
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
  f(arg) + f(arg)
}
fn main() {
  let answer = do_twice(add_one, 5);
  println!("The answer is: {}", answer);
}例子一
fn main() {
  let list_of_numbers = vec![1, 2, 3];
  let list_of_strings: Vec<String> = list_of_numbers
  .iter().map(|i| i.to_string()).collect();
  let list_of_numbers = vec![1, 2, 3];
  let list_of_strings: Vec<String> = list_of_numbers
  .iter().map(ToString::to_string).collect();
}例子二
fn main() {
  enum Status {
    Value(u32),
    Stop,
  }
  let v = Status::Value(3);
  let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
}fn returns_closure() -> Fn(i32) -> i32 { // 报错 没有一个已知的大小
  |x| x + 1
}
fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
  Box::new(|x| x + 1)
}
fn main() {
}// let v: Vec<u32> = vec![1, 2, 3];
#[macro_export]
macro_rules! vec {
  ($($x:expr),*) => {
    {
      let mut temp_vec = Vec::new();
      $(
        temp_vec.push($x);
      )*
      temp_vec
    }
  };
}
// let mut temp_vec = Vec::new();
// temp_vec.push(1);
// temp_vec.push(2);
// temp_vec.push(3);
// temp_vecuse proc_macro;
#[some_attribute]
pub fn some_name(input: TokenStream) -> TokenStream {
}➜ cd rust
~/rust
➜ cargo new hello_macro --lib
     Created library `hello_macro` package
~/rust
➜ cd hello_macro
hello_macro on  master [?] via 🦀 1.67.1
➜ c
hello_macro on  master [?] via 🦀 1.67.1
➜
hello_macro on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ cd ..         
~/rust 
➜ cargo new hello_macro_derive --lib
     Created library `hello_macro_derive` package
~/rust 
➜ cd hello_macro_derive             
hello_macro_derive on  master [?] via 🦀 1.67.1 
➜ c                    
hello_macro_derive on  master [?] via 🦀 1.67.1 
➜ 
hello_macro_derive 代码:
Cargo.toml
[package]
name = "hello_macro_derive"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
syn = "2.0.13"
quote = "1.0.26"
src/lib.rs
extern crate proc_macro;
use crate::proc_macro::TokenStream;
use quote::quote;
use syn;
// #[derive(HelloMacro)]
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Construct a representation of Rust code as a syntax tree
    // that we can manipulate
    let ast = syn::parse(input).unwrap();
    // Build the trait implementation
    impl_hello_macro(&ast)
}
fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() {
                println!("Hello, Macro! My name is {}", stringify!(#name));
            }
        }
    };
    gen.into()
}
// DeriveInput {
//     // --snip--
//     ident: Ident {
//         ident: "Pancakes",
//         span: #0 bytes(95..103)
//     },
//     data: Struct(
//         DataStruct {
//             struct_token: Struct,
//             fields: Unit,
//             semi_token: Some(
//                 Semi
//             )
//         }
//     )
// }
hello_macro 代码:
main.rs
use hello_macro::HelloMacro;
struct Pancakes;
impl HelloMacro for Pancakes {
    fn hello_macro() {
        println!("Hello, Macro! My name is Pancakes!");
    }
}
fn main() {
    Pancakes::hello_macro();
}
// use hello_macro::HelloMacro;
// use hello_macro_derive::HelloMacro;
// #[derive(HelloMacro)]
// struct Pancakes;
// fn main() {
//     Pancakes::hello_macro();
// }
lib.rs
pub trait HelloMacro {
    fn hello_macro();
}
编译
hello_macro_derive on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ cargo build
   Compiling unicode-ident v1.0.8
   Compiling proc-macro2 v1.0.56
   Compiling quote v1.0.26
   Compiling syn v2.0.15
   Compiling hello_macro_derive v0.1.0 (/Users/qiaopengjun/rust/hello_macro_derive)
    Finished dev [unoptimized + debuginfo] target(s) in 1.54s
hello_macro_derive on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ 
hello_macro on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ cargo build                       
   Compiling hello_macro v0.1.0 (/Users/qiaopengjun/rust/hello_macro)
    Finished dev [unoptimized + debuginfo] target(s) in 0.26s
hello_macro on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ 
创建
~/rust
➜ cargo new pancakes
     Created binary (application) `pancakes` package
~/rust
➜ cd pancakes
pancakes on  master [?] via 🦀 1.67.1
➜ c
pancakes on  master [?] via 🦀 1.67.1
➜
main.rs 文件
use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;
#[derive(HelloMacro)]
struct Pancakes;
fn main() {
    Pancakes::hello_macro();
}
Cargo.toml 文件
[package]
name = "pancakes"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
hello_macro = {path = "../hello_macro"}
hello_macro_derive = {path = "../hello_macro_derive"}
运行
pancakes on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ cargo run         
   Compiling hello_macro v0.1.0 (/Users/qiaopengjun/rust/hello_macro)
   Compiling pancakes v0.1.0 (/Users/qiaopengjun/rust/pancakes)
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
     Running `target/debug/pancakes`
Hello, Macro! My name is Pancakes
pancakes on  master [?] is 📦 0.1.0 via 🦀 1.67.1 
➜ // #[route(GET, "/")]
// fn index() {}
// #[proc_macro_attribute]
// pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {}// let sql = sql(SELECT * FROM posts WHERE id=1);
// #[proc_macro]
// pub fn sql(input: TokenStream) -> TokenStream {} 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!