跳至主要內容
Rust随笔(八)

Rust随笔(八)

今天来谈谈Rust里面的Sync和Send,在随笔七里面我们提到这两个概念,今天我们来详细的说一下。这两个trait是rust异步编程的主要基石之一。我们首先看看定义:

  1. Send Send 表示一个类型的所有权可以安全地在线程之间转移。
  2. Sync Sync 表示一个类型的不可变引用&T)可以安全地在线程之间共享。 只有同时实现这两者,才能在多线程环境下共享数据,看着定义我们会感到有点疑惑,接下来我们用例子说明。

Mr.Lexon大约 13 分钟rustrustasynchronous-programming
Rust基础(二)

Rust基础(二)

在前面一章我们介绍了什么是OOPRust思想上的区别,以及Rust的一些基础语法和核心思想。 本章我们围绕OOPObjectInterface,RustStructTrait,介绍他们的基础语法以及核心思想,并且对其进行对比以及优势比较。

OOP

对于OOP来说,ObjectInterface几乎熟悉得不能再熟悉了,几乎所有的编程设计都是围绕ObjectOOP的三大基本原则:


Mr.Lexon大约 15 分钟rustrustfoundation
Rust随笔(七)

Rust随笔(七)

我们前面介绍了Arc<Mutex<T>>这个东西,本篇我们以此为引子,打开Rust编程中异步编程的门。

什么是异步编程

几乎每一个编程语言都能做到异步编程,那么什么是异步编程呢?这里举一个例子:

  1. A要去做n件事情
  2. 这些事情并不会立马出结果,并且需要等待,每件事情假设处理的时间为m,等待的时间为w
  3. 要在尽可能短的时间内做完并收集起来(假设每件事情收集完成的速度为t)
  4. 已知这些事情并没有关联 那么假设我们一件事情一件事情的做,那么所有事情做完就等于n * (m + w + t),公式看起来不大,但是如果时间单位是秒,n是一个很大的数(比如说1百万),那么处理起来就很吓人了,从上面我们得到一个条件,就是每一件事情没有关联,那么我们就可以在处理这些事情的时候,在等待期间就可以做其他事情,那么按照这样的思路做,时间就变成了(n * m) + w + (n * t)(调度的时间在这里为了简化所以忽略不计),这样看时间是不是少了一个数量级,如果我们加多一些人手来做,假设添加了p个人,那么时间就变成了(n * (m + t)) / p + w,这样是不是又少了一个数量级。所以这个就是异步编程的核心思想: 协作式调度非阻塞等待。任务在遇到需要等待的操作(如网络请求)时,会主动让出执行权,这样同一个工作线程就可以立刻去处理其他准备就绪的任务。这极大地提高了在 I/O 密集型场景下的资源利用率。 这里只是大致的描述一下异步编程,异步编程本身又非常多的概念,比如说并行,并发,同步,异步,资源调度等等。这些概念可以自行了解。接下来,我们介绍一下操作异步的基本单位:协程,与之相关的:线程和进程。

Mr.Lexon大约 10 分钟rustrustasynchronous-programming
Rust随笔(六)

Rust随笔(六)

我们在随笔五中提到过RcRefCell的概念,这两个工具给复杂的变量引用场景给予了强大的支持,这里有个问题,我们首先看看下面这一段代码:

use std::rc::Rc;
use std::thread;

fn main() {
    let data = Rc::new(5);
    let data_clone = Rc::clone(&data);
    
    thread::spawn(move || {
        println!("Data from new thread: {}", data_clone);
    });
}

Mr.Lexon大约 9 分钟rustrustRcArc
rust基础(一)

Rust基础(一)

rust编程语言,一个极其现代性的编程语言,由于其特殊的语法规则以及函数式概念,劝退了大量的来自OOP或者是第一门语言是OOP并且没有接触过函数式编程的新手。基于此,本文探讨如何编写rust程序。本文是一个系列文章,主要探讨的是rust这门语言如何从OOP基础上入门,而且本系列不做具体的项目分析和构建,而是采用从OOP的视角和添加一些函数式编程概念去解释rust语法和核心思想。所以,这个系列并不会很长,而且需要有一定的OOP编程经验才可以理解(如果只学过js或者其他脚本类型或可视化的编程语言,建议亲自编写OOP项目再行学习)。 本系列所有使用的例子,不一定都是符合rust编程理念的,但是一定符合新手学习的,而且,再看本系列文章之前,需要普及一个概念,就是:


Mr.Lexon大约 18 分钟rustrustfoundation
rust随笔(五)

Rust随笔(五)

本篇讨论两个东西:

  1. RcRefCell
  2. Reference (&) (在这里我们用引用代替Reference) 在前面的随笔中,提到了“引用”的概念,我们回顾一下这个基础函数:
fn judge_size<'a>(x:&'a str,y:&'a str) -> &'a str {
	if (x > y){
		x
	}else{
		y
	}
}

Mr.Lexon大约 12 分钟rustrustRc
rust随笔(四)

Rust随笔(四)

在 Rust 编程中,我们经常需要在不同的状态和结果表示之间进行转换。例如,一个简单的布尔条件判断可能需要升级为一个更具描述性的 Option 或包含错误信息的 Result。同样,我们也常常需要从 ResultOption 中提取出布尔状态。这些转换虽然基础,但掌握其实现方式能显著提升代码的可读性和函数的连贯性。这里是一些常见需求:

  1. bool -> Result
  2. bool -> Option
  3. Option -> Result 基于这些需求,以下提供示例代码:

Mr.Lexon大约 2 分钟rustrust
rust 随笔(三)

Rust 随笔(三)

thiserror

这篇文章探讨一个常见的错误处理库——thiserror 首先我们回顾一下上一篇的Error第二种用法:

#[derive(Debug)]
pub enum AppError {
    Config(ConfigError),
    Database(DatabaseError),
    Query(QueryError),
    Io(io::Error), // 有时也可能直接暴露一些通用的 IO 错误
    Initialization(String), // 其他初始化错误
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            AppError::Config(err) => write!(f, "{}", err), // 直接调用 ConfigError 的 Display
            AppError::Database(err) => write!(f, "{}", err), // 直接调用 DatabaseError 的 Display
            AppError::Query(err) => write!(f, "{}", err),
            AppError::Io(err) => write!(f, "IO 错误: {}", err),
            AppError::Initialization(msg) => write!(f, "初始化错误: {}", msg),
        }
    }
}

impl Error for AppError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            AppError::Config(err) => Some(err),    // ConfigError 实现了 Error,可以作为 source
            AppError::Database(err) => Some(err),  // DatabaseError 实现了 Error
            AppError::Query(err) => Some(err),     // QueryError 实现了 Error
            AppError::Io(err) => Some(err),        // io::Error 本身就实现了 Error
            AppError::Initialization(_) => None,
        }
    }
}

// 实现 From trait
impl From<ConfigError> for AppError {
    fn from(err: ConfigError) -> Self {
        AppError::Config(err)
    }
}

impl From<DatabaseError> for AppError {
    fn from(err: DatabaseError) -> Self {
        AppError::Database(err)
    }
}

impl From<QueryError> for AppError {
    fn from(err: QueryError) -> Self {
        AppError::Query(err)
    }
}

impl From<io::Error> for AppError { // 有时也希望直接转换IO错误
    fn from(err: io::Error) -> Self {
        AppError::Io(err)
    }
}

Mr.Lexon大约 4 分钟rustrustthiserror
rust 随笔(二)

Rust 随笔(二)

这篇文章探讨在Rust中自定义Error如何设计,我们先直接给出一个例子:

use std::fmt;

#[derive(Debug)]
enum CustomError {
    CustomErrorKind1,
    CustomErrorKind2(String),
    CustomErrorKind3(String, String),
}
//实现Display,用于呈现错误结构
impl fmt::Display for CustomError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            CustomError::CustomErrorKind1 => write!(f, "Custom Error Type 1 Occurred"),
            CustomError::CustomErrorKind2(s) => write!(f, "Custom Error Type 2 Occurred: {}", s),
            CustomError::CustomErrorKind3(s1, s2) => write!(f, "Custom Error Type 3 Occurred: {} - {}", s1, s2),
        }
    }
}

//通用化
impl std::error::Error for CustomError {}

// Example of how to use it:
fn main() {
    let error1 = CustomError::CustomErrorKind1;
    let error2 = CustomError::CustomErrorKind2("Something went wrong".to_string());
    let error3 = CustomError::CustomErrorKind3("File not found".to_string(), "Ensure the path is correct".to_string());

    println!("{}", error1);
    println!("{}", error2);
    println!("{}", error3);

    // For debug formatting
    println!("{:?}", error1);
    println!("{:?}", error2);
    println!("{:?}", error3);
}

Mr.Lexon大约 8 分钟rustrust
rust随笔(一)

Rust随笔(一)

最近将《the book》看到了闭包部分,感触良多,发现rust的设计其实和oop关系不大,并且“组合优于继承”这句话不仅仅只是和结构体说的,还是对函数说的。本篇探讨一下问题:

  1. 何为生命周期
  2. rust和代码整洁之道有什么关系
  3. 为什么说学好组合子就学会了rust基本思想了

何为生命周期

我这里不从具体的函数定义出发,我从闭包出发,在定义中,闭包有以下trait

trait Fn;
trait FnOnce;
trait FnMut;

Mr.Lexon大约 14 分钟rustrustfunctional-program