Rc 和 Arc 源码对比 #
// Rc源码片段
impl<T: ?Sized> !marker::Send for Rc<T> {}
impl<T: ?Sized> !marker::Sync for Rc<T> {}
// Arc源码片段
unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
! 代表移除特征的相应实现,上面代码中 Rc<T>
的 Send 和 Sync 特征被特地移除了实现
Arc<T>
则相反,实现了 Sync + Send
为裸指针实现Send #
unsafe 代码块包裹,实现Send 和Sync 是 unsafe 特征
use std::thread;
#[derive(Debug)]
struct MyBox(*mut u8);
unsafe impl Send for MyBox {}
fn main() {
let p = MyBox(5 as *mut u8);
let t = thread::spawn(move || {
println!("{:?}", p);
});
t.join().unwrap();
}
为裸指针实现Sync #
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
#[derive(Debug)]
struct MyBox(*const u8);
// 访问的引用实际上还是对主线程中的数据的借用,转移进来的仅仅是外层的智能指针引用
// 为 MyBox 实现 Sync
unsafe impl Sync for MyBox {}
fn main() {
let b = &MyBox(5 as *const u8);
let v = Arc::new(Mutex::new(b));
let t = thread::spawn(move || {
let _v1 = v.lock().unwrap();
});
t.join().unwrap();
}
- 实现 Send 的类型可以在线程间安全的传递其所有权, 实现 Sync 的类型可以在线程间安全的共享(通过引用)
- 绝大部分类型都实现了 Send 和 Sync ,常见的未实现的有:裸指针、 Cell 、 RefCell 、 Rc
- 可以为自定义类型实现 Send 和 Sync ,但是需要 unsafe 代码块
- 可以为部分 Rust 中的类型实现 Send 、 Sync ,但是需要使用 newtype
全局变量 #
const MAX_ID: usize = usize::MAX / 2;
// 静态变量不会被内联,在整个程序中,静态变量只有一个实例,所有的引用都会指向同一个地址
// 存储在静态变量中的值必须要实现 Sync trait
static mut REQUEST_RECV: usize = 0;
fn main() {
println!("用户ID允许的最大值是{}", MAX_ID);
unsafe {
REQUEST_RECV += 1;
assert_eq!(REQUEST_RECV, 1);
}
}
想要全局计数器、状态控制等功能,又想要线程安全的实现,原子类型是非常好的办法。
use std::sync::atomic::{AtomicUsize, Ordering};
static REQUEST_RECV: AtomicUsize = AtomicUsize::new(0);
fn main() {
for _ in 0..100 {
REQUEST_RECV.fetch_add(1, Ordering::Relaxed);
}
println!("当前用户请求数{:?}", REQUEST_RECV);
}
use std::sync::atomic::{AtomicUsize, Ordering};
struct Factory {
factory_id: usize,
}
static GLOBAL_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
const MAX_ID: usize = usize::MAX / 2;
fn generate_id() -> usize {
// 检查两次溢出,否则直接加一可能导致溢出
let current_val = GLOBAL_ID_COUNTER.load(Ordering::Relaxed);
if current_val > MAX_ID {
panic!("Factory ids overflowed");
}
let next_id = GLOBAL_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if next_id > MAX_ID {
panic!("Factory ids overflowed");
}
next_id
}
impl Factory {
fn new() -> Self {
Self {
factory_id: generate_id(),
}
}
}
fn main() {
let factory = Factory::new();
println!("factory id: {}", factory.factory_id);
println!("factory id: {}", factory.factory_id);
}
lazy_static #
use lazy_static::lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref HASHMAP: HashMap<u32, &'static str> = {
let mut m = HashMap::new();
m.insert(0, "foo");
m.insert(1, "bar");
m.insert(2, "baz");
m
};
}
pub fn lazy_test() {
// 首次访问`HASHMAP`的同时对其进行初始化
println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
// 后续的访问仅仅获取值,再不会进行任何初始化操作
println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap());
}
// The entry for `0` is "foo".
// The entry for `1` is "bar".
函数中返回全局变量 #
#[derive(Debug)]
struct Config {
a: String,
b: String,
}
static mut CONFIG: Option<&mut Config> = None;
fn init() -> Option<&'static mut Config> {
let c = Box::new(Config {
a: "A".to_string(),
b: "B".to_string(),
});
Some(Box::leak(c))
}
fn main() {
unsafe {
CONFIG = init();
println!("{:?}", CONFIG)
}
}
错误处理 #
fn main() {
{
// and_then with Option
let s1 = Some("some1");
let s2 = Some("some2");
let fn_some = |_| Some("some2"); // 类似于: let fn_some = |_| -> Option<&str> {Some("some2") };
let n: Option<&str> = None;
let fn_none = |_| None;
assert_eq!(s1.and_then(fn_some), s2); // Some1 and_then Some2 = Some2
assert_eq!(s1.and_then(fn_none), n); // Some and_then None = None
assert_eq!(n.and_then(fn_some), n); // None and_then Some = None
assert_eq!(n.and_then(fn_none), n); // None1 and_then None2 = None1
// and_then with Result
let o1: Result<&str, &str> = Ok("ok1");
let o2: Result<&str, &str> = Ok("ok2");
let fn_ok = |_| Ok("ok2"); // 类似于: let fn_ok = |_| -> Result<&str, &str> {Ok("ok2") };
let e1: Result<&str, &str> = Err("error1");
let e2: Result<&str, &str> = Err("error2");
let fn_err = |_| Err("error2");
assert_eq!(o1.and_then(fn_ok), o2); // Ok1 and_then Ok2 = Ok2
assert_eq!(o1.and_then(fn_err), e2); // Ok and_then Err = Err
assert_eq!(e1.and_then(fn_ok), e1); // Err and_then Ok = Err
assert_eq!(e1.and_then(fn_err), e1); // Err1 and_then Err2 = Err1
}
// filter 用于对 Option 进行过滤
{
let s1 = Some(3);
let s2 = Some(6);
let n = None;
let fn_is_even = |x: &i8| x % 2 == 0;
assert_eq!(s1.filter(fn_is_even), n); // Some(3) -> 3 is not even -> None
assert_eq!(s2.filter(fn_is_even), s2); // Some(6) -> 6 is even -> Some(6)
assert_eq!(n.filter(fn_is_even), n); // None -> no value -> None
}
// map 可以将 Some 或 Ok 中的值映射为另一个
{
let s1 = Some("abcde");
let s2 = Some(5);
let n1: Option<&str> = None;
let n2: Option<usize> = None;
let o1: Result<&str, &str> = Ok("abcde");
let o2: Result<usize, &str> = Ok(5);
let e1: Result<&str, &str> = Err("abcde");
let e2: Result<usize, &str> = Err("abcde");
let fn_character_count = |s: &str| s.chars().count();
assert_eq!(s1.map(fn_character_count), s2); // Some1 map = Some2
assert_eq!(n1.map(fn_character_count), n2); // None1 map = None2
assert_eq!(o1.map(fn_character_count), o2); // Ok1 map = Ok2
assert_eq!(e1.map(fn_character_count), e2); // Err1 map = Err2
}
// map 可以将 Some 或 Ok 中的值映射为另一个
{
let s1 = Some("abcde");
let s2 = Some(5);
let n1: Option<&str> = None;
let n2: Option<usize> = None;
let o1: Result<&str, &str> = Ok("abcde");
let o2: Result<usize, &str> = Ok(5);
let e1: Result<&str, &str> = Err("abcde");
let e2: Result<usize, &str> = Err("abcde");
let fn_character_count = |s: &str| s.chars().count();
assert_eq!(s1.map(fn_character_count), s2); // Some1 map = Some2
assert_eq!(n1.map(fn_character_count), n2); // None1 map = None2
assert_eq!(o1.map(fn_character_count), o2); // Ok1 map = Ok2
assert_eq!(e1.map(fn_character_count), e2); // Err1 map = Err2
}
{
const V_DEFAULT: u32 = 1;
let s: Result<u32, ()> = Ok(10);
let n: Option<u32> = None;
let fn_closure = |v: u32| v + 2;
assert_eq!(s.map_or(V_DEFAULT, fn_closure), 12);
assert_eq!(n.map_or(V_DEFAULT, fn_closure), V_DEFAULT);
}
{
let s = Some(10);
let n: Option<i8> = None;
let fn_closure = |v: i8| v + 2;
let fn_default = || 1;
assert_eq!(s.map_or_else(fn_default, fn_closure), 12);
assert_eq!(n.map_or_else(fn_default, fn_closure), 1);
let o = Ok(10);
let e = Err(5);
let fn_default_for_result = |v: i8| v + 1; // 闭包可以对 Err 中的值进行处理,并返回一个新值
assert_eq!(o.map_or_else(fn_default_for_result, fn_closure), 12);
assert_eq!(e.map_or_else(fn_default_for_result, fn_closure), 6);
}
{
let s = Some("abcde");
let n: Option<&str> = None;
let fn_err_message = || "error message";
let o: Result<&str, &str> = Ok("abcde");
let e: Result<&str, &str> = Err("error message");
assert_eq!(s.ok_or_else(fn_err_message), o); // Some(T) -> Ok(T)
assert_eq!(n.ok_or_else(fn_err_message), e); // None -> Err(default)
}
}
use std::fs::File;
use std::io;
#[derive(Debug)]
struct AppError {
kind: String, // 错误类型
message: String, // 错误信息
}
// 为 AppError 实现 std::convert::From 特征,由于 From 包含在 std::prelude 中,因此可以直接简化引入。
// 实现 From<io::Error> 意味着我们可以将 io::Error 错误转换成自定义的 AppError 错误
impl From<io::Error> for AppError {
fn from(error: io::Error) -> Self {
AppError {
kind: String::from("io"),
message: error.to_string(),
}
}
}
fn main() -> Result<(), AppError> {
// ? 可以将错误进行隐式的强制转换
// File::open 返回的是 std::io::Error , 我们并没有进行任何显式的转换,它就能自动变成AppError ,这就是 ? 的强大之处
let _file = File::open("nonexistent_file.txt")?;
Ok(())
}
use std::fs::File;
use std::io::{self, Read};
use std::num;
#[derive(Debug)]
struct AppError {
kind: String,
message: String,
}
impl From<io::Error> for AppError {
fn from(error: io::Error) -> Self {
AppError {
kind: String::from("io"),
message: error.to_string(),
}
}
}
impl From<num::ParseIntError> for AppError {
fn from(error: num::ParseIntError) -> Self {
AppError {
kind: String::from("parse"),
message: error.to_string(),
}
}
}
fn main() -> Result<(), AppError> {
let mut file = File::open("hello_world.txt")?;
let mut content = String::new();
file.read_to_string(&mut content)?;
let _number: usize;
_number = content.parse()?;
Ok(())
}
// 01. 若 hello_world.txt 文件不存在
Error: AppError { kind: "io", message: "No such file or directory (os error 2)" }
// 02. 若用户没有相关的权限访问 hello_world.txt
Error: AppError { kind: "io", message: "Permission denied (os error 13)" }
// 03. 若 hello_world.txt 包含有非数字的内容,例如 Hello, world!
Error: AppError { kind: "parse", message: "invalid digit found in string" }
指针 #
创建裸指针是安全的行为,而解引用裸指针才是不安全的行为 :
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
unsafe {
println!("r1 is: {}", *r1);
}
let r2 = &mut num as *mut i32;
unsafe {
println!("r1 is: {}", *r1);
}
}
基于智能指针创建裸指针 #
let a: Box<i32> = Box::new(10);
// 需要先解引用a
let b: *const i32 = &*a;
// 使用 into_raw 来创建
let c: *const i32 = Box::into_raw(a);