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_vec
use 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 {}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!