Rust Web 全栈开发(七):错误处理

Rust web开发 ActixWeb 入门 目前,Actix Web 仍然是 Rust Web 后端生态系统中极其强大的竞争对手。尽管之前的事件可能对其产生影响,但它仍然很强大,并且是 Rust 中最受推荐的 Web 框架之一。最初基于同名的 actor 框架 (actix),后来它已经消失,并且actix现在仅用于 websocket 端点。本文将主要讨论 v4.4。 阅读详情

Rust Web 全栈开发(七):错误处理

参考视频:https://www.bilibili.com/video/BV1RP4y1G7KF

继续之前的 Actix 项目。

统一的错误处理

我们希望在 Web Service 中实现统一了错误处理。

在这里插入图片描述

将程序运行中的各种错误,归类为自定义错误类型,再转化为 HTTP Response 发送给客户端。

Actix 框架中的错误处理

Actix-Web 定义了一个通用的错误类型结构体 actix-web::error::Error,它实现了 std::error::Error 这个 trait。

任何实现了标准库 Error trait 的类型,都可以通过 ? 运算符,转换为 Actix 的 Error 类型。Actix 的 Error 类型会自动转换为 HTTP Response,返回给客户端。

ResponseError trait:任何实现该 trait 的错误均可转化为 HTTP Response 消息。

Actix-Web 对于常见的错误有内置的实现,例如:

  • Rust 标准 I/O 错误
  • Serde 错误
  • Web 错误,例如:ProtocolError、Utf8Error、ParseError 等等

对于其他没有内置实现的错误类型,需要自定义实现错误到 HTTP Response 的转换。

创建自定义错误处理器

  1. 创建一个自定义错误类型
  2. 实现 From trait,用于把其它错误类型转化为该类型
  3. 为自定义错误类型实现 ResponseError trait
  4. 在 handler 里返回自定义错误类型
  5. Actix 会把错误转化为 HTTP 响应

在 webservice/src 目录下新建一个 errors.rs,添加以下代码:

use actix_web::{error, http::StatusCode, HttpResponse, Result};
use serde::Serialize;
use sqlx::error::Error as SQLxError;
use std::fmt;

#[derive(Debug, Serialize)]
pub enum MyError {
    DBError(String),
    ActixError(String),
    NotFound(String),
}

#[derive(Debug, Serialize)]
pub struct MyErrorResponse {
    error_message: String,
}

impl MyError {
    fn error_response(&self) -> String {
        match self {
            MyError::DBError(msg) => {
                println!("Database error occurred: {:?}", msg);
                "Database error".into()
            }
            MyError::ActixError(msg) => {
                println!("Server error occurred: {:?}", msg);
                "Internal server error".into()
            }
            MyError::NotFound(msg) => {
                println!("Not found error occurred: {:?}", msg);
                msg.into()
            }
        }
    }
}

impl error::ResponseError for MyError {
    fn status_code(&self) -> StatusCode {
        match self {
            MyError::DBError(_msg) | MyError::ActixError(_msg) => StatusCode::INTERNAL_SERVER_ERROR,
            MyError::NotFound(_msg) => StatusCode::NOT_FOUND,
        }
    }

    fn error_response(&self) -> HttpResponse {
        HttpResponse::build(self.status_code()).json(MyErrorResponse {
            error_message: self.error_response(),
        })
    }
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self)
    }
}

impl From<actix_web::error::Error> for MyError {
    fn from(err: actix_web::error::Error) -> Self {
        MyError::ActixError(err.to_string())
    }
}

impl From<SQLxError> for MyError {
    fn from(err: SQLxError) -> Self {
        MyError::DBError(err.to_string())
    }
}

ResponseError trait 要求实现类型实现 Debug 和 Display trait。其中,Debug trait 有默认实现,Display trait 需要自己实现。

引入 errors 模块

修改 teacher_service.rs,引入 errors 模块:

#[path = "../errors.rs"]
mod errors;

修改 db_access

修改 db_access.rs,每个数据库操作的函数的返回值改为 Result:

use super::models::*;
use sqlx::MySqlPool;
use super::errors::MyError;

pub async fn get_courses_for_teacher_db(pool: &MySqlPool, teacher_id: i32) -> Result<Vec<Course>, MyError> {
    let rows: Vec<Course> = sqlx::query_as(
        "SELECT id, teacher_id, name, time
            FROM course
            WHERE teacher_id = ?"
    )
        .bind(teacher_id)
        .fetch_all(pool) // 获取所有记录
        .await?;

    let courses: Vec<Course> = rows.iter()
        .map(|r| Course {
            id: Some(r.id.expect("Unknown")),
            teacher_id: r.teacher_id,
            name: r.name.clone(),
            time: Some(chrono::NaiveDateTime::from(r.time.unwrap())),
        })
        .collect();

    match courses.len() {
        0 => Err(MyError::NotFound("Course not found for teacher".into())),
        _ => Ok(courses),
    }
}

pub async fn get_course_details_db(pool: &MySqlPool, teacher_id: i32, course_id: i32) -> Result<Course, MyError> {
    let row: Result<Course, sqlx::Error> = sqlx::query_as(
        "SELECT id, teacher_id, name, time
            FROM course
            WHERE teacher_id = ? and id = ?"
    )
        .bind(teacher_id)
        .bind(course_id)
        .fetch_one(pool) // 获取单条记录
        .await;

    if let Ok(row) = row {
        Ok(Course {
            id: Some(row.id.expect("Unknown")),
            teacher_id: row.teacher_id,
            name: row.name.clone(),
            time: Some(chrono::NaiveDateTime::from(row.time.unwrap())),
        })
    } else {
        Err(MyError::NotFound("Course didn't founded".into()))
    }
}

pub async fn post_new_course_db(pool: &MySqlPool, new_course: Course) -> Result<(), MyError> {
    let _insert_query = sqlx::query!(
        "INSERT INTO course (id, teacher_id, name, time)
            VALUES (?, ?, ?, ?)",
        new_course.id.unwrap(),
        new_course.teacher_id,
        new_course.name,
        new_course.time
    )
        .execute(pool)
        .await?;

    Ok(())
}

修改 handler

修改 handlers.rs,同样将函数的返回值改为 Result,对应的测试函数也要修改。

use super::state::AppState;
use actix_web::{web, HttpResponse};
use super::models::Course;
use super::db_access::*;
use super::errors::MyError;

pub async fn health_check_handler(app_state: web::Data<AppState>) -> HttpResponse {
    println!("incoming for health check");

    let health_check_response = &app_state.health_check_response;
    let mut visit_count = app_state.visit_count.lock().unwrap();
    let response = format!("{} {} times", health_check_response, visit_count);
    *visit_count += 1;

    HttpResponse::Ok().json(&response)
}

pub async fn new_course(
    new_course: web::Json<Course>,
    app_state: web::Data<AppState>,
) -> Result<HttpResponse, MyError> {
    post_new_course_db(&app_state.db, new_course.into())
        .await
        .map(|course| HttpResponse::Ok().json(course))
}

pub async fn get_courses_for_teacher(
    app_state: web::Data<AppState>,
    params: web::Path<i32>,
) -> Result<HttpResponse, MyError> {
    let teacher_id = params.into_inner();
    get_courses_for_teacher_db(&app_state.db, teacher_id)
        .await
        .map(|courses| HttpResponse::Ok().json(courses))
}

pub async fn get_course_detail(
    app_state: web::Data<AppState>,
    params: web::Path<(i32, i32)>,
) -> Result<HttpResponse, MyError> {
    let (teacher_id, course_id) = params.into_inner();
    get_course_details_db(&app_state.db, teacher_id, course_id)
        .await
        .map(|course| HttpResponse::Ok().json(course))
}

#[cfg(test)]
mod tests {
    use super::*;
    use actix_web::http::StatusCode;
    use std::sync::Mutex;
    use dotenv::dotenv;
    use sqlx::mysql::MySqlPoolOptions;
    use std::env;
    use chrono::{NaiveDate, NaiveDateTime, NaiveTime};

    #[actix_rt::test]
    async fn post_course_test() {
        // 检测并读取 .env 文件中的内容,若不存在也会跳过异常
        dotenv().ok();

        let db_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL 没有在 .env 文件里设置");

        // 创建数据库连接池
        let db_pool = MySqlPoolOptions::new()
            .connect(&db_url)
            .await
            .unwrap();

        let course = web::Json(Course {
            teacher_id: 1,
            name: "Test course".into(),
            id: Some(3),
            time: Some(NaiveDateTime::new(
                NaiveDate::from_ymd_opt(2025, 7, 12).expect("Unknown date"),
                NaiveTime::from_hms_opt(10, 15, 0).expect("Unknown time"),
            )),
        });

        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            db: db_pool,
        });

        // 模拟添加课程的请求
        let response = new_course(course, app_state).await.unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn get_all_courses_success() {
        // 检测并读取 .env 文件中的内容,若不存在也会跳过异常
        dotenv().ok();

        let db_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL 没有在 .env 文件里设置");

        // 创建数据库连接池
        let db_pool = MySqlPoolOptions::new()
            .connect(&db_url)
            .await
            .unwrap();

        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            db: db_pool,
        });

        let teacher_id: web::Path<i32> = web::Path::from(1);
        let response = get_courses_for_teacher(app_state, teacher_id).await.unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }

    #[actix_rt::test]
    async fn get_one_course_success() {
        // 检测并读取 .env 文件中的内容,若不存在也会跳过异常
        dotenv().ok();

        let db_url = env::var("DATABASE_URL")
            .expect("DATABASE_URL 没有在 .env 文件里设置");

        // 创建数据库连接池
        let db_pool = MySqlPoolOptions::new()
            .connect(&db_url)
            .await
            .unwrap();

        let app_state: web::Data<AppState> = web::Data::new(AppState {
            health_check_response: "".to_string(),
            visit_count: Mutex::new(0),
            db: db_pool,
        });

        let params: web::Path<(i32, i32)> = web::Path::from((1, 1));
        let response = get_course_detail(app_state, params).await.unwrap();

        assert_eq!(response.status(), StatusCode::OK);
    }
}

如果发生了错误,得到的结果就是 MyError。因为 MyError 实现了 ResponseError trait,Actix 框架会自动转换为错误对应的 HTTP Response。

测试

在终端执行命令 cargo test --bin teacher_service,三个测试都通过了:

在这里插入图片描述

cd 到 webservice,执行命令 cargo run,在浏览器中测试两种错误类型:

在这里插入图片描述

在这里插入图片描述

终端也会打印错误信息:

在这里插入图片描述

㈠. Rust语言 web框架actix-web和sqlx的踩坑日记 + 搭环境 学了好几个月的Rust, 终于上手写一个web项目, 处处是坑, 某些地方卡住了我一周多时间, 分享几个坑, 给后来的小伙伴 本人电脑环境 我尽可能少依赖第三方库, 做一个干净, 比较少的代码让大家看懂, 给大家提供一个模板 第一个坑 今天, 也就是2021年6月30日, 目前的actix-web的最新版本是3.3.2, 同时actix-web的异步运行时是基于tokio 0.1x系列构建的 与此同时, sqlx的最新版本是0.5.5, 这个第三方库运行时是基于tokio1.x系列的 也就是说, 阅读详情

相关推荐

Rust后端管理系统实战:Actix-web全栈方案

摘要:本文介绍了基于Actix-web框架的多个Rust后端管理系统实现方案,包括CRM客户关系管理系统、MIS管理系统和供应商管理系统。这些系统均采用模块化设计,包含数据库模型定义、路由处理、业务逻辑实现等核心模块,并支持PostgreSQL/SQLite数据库集成。文章详细展示了各系统的代码结构、Docker容器化部署方法以及Kubernetes集群配置方案,同时提供了完整的API接口示例和测试方法。此外还整理了开发过程中常用的Docker、Kubernetes和Rust操作命令,覆盖了从项目初始化到生

keny-大成的博客 1630

105、Rust Web开发利器:Actix-Web与Warp框架解析

本文深入探讨了Rust语言的两个著名Web开发框架:Actix-Web和Warp。Actix-Web以异步处理能力和丰富的生态为特点,适用于高并发Web应用和RESTful API的构建;而Warp则以函数式编程风格和高度模块化的设计见长,适合构建模块化程度高、需要精细控制的Web应用。两者均具有Rust语言的性能特性和类型安全性。通过比较分析,本文帮助开发者根据项目需求和团队偏好选择合适的框架,提高开发效率和产品质量。

silenceallat的博客 2685

【Actix Web】Rust Web开发JWT认证

在现代 Web 开发中,JWT(JSON Web Token)是一种常用的无状态认证方式。通过 JWT,服务端可以发放加密令牌给客户端,客户端每次请求时携带此令牌,服务器通过验证令牌来识别用户身份,省去了服务器端存储会话信息的负担。 Rust 作为一门性能与安全兼备的系统级编程语言,结合 Actix Web 框架开发高性能 Web 应用,成为后端开发的新趋势。

景天科技苑 1万+

[Rust实战]初探 actix_web

Rust语言的特点 高性能- Rust 速度惊人且内存利用率极高。由于没有运行时和垃圾回收,它能够胜任对性能要求特别高的服务,可以在嵌入式设备上运行,还能轻松和其他语言集成。 可靠性- Rust 丰富的类型系统和所有权模型保证了内存安全和线程安全,让您在编译期就能够消除各种各样的错误。 生产力- Rust 拥有出色的文档、友好的编译器和清晰的错误提示信息, 还集成了一流的工具 —— 包管理器和构建工具, 智能地自动补全和类型检验的多编辑器支持, 以及自动格式化代码等等。...

学生董格 1973

Rust中Web服务错误处理与重构实践

本文深入探讨了Rust语言在Web服务开发中对错误处理的处理方式,以及如何应对项目需求变更带来的重构挑战。通过实践,我们学习了如何将错误类型转换为HTTP响应消息,并通过Actix Web框架将自定义错误自动转换为有意义的HTTP响应。文章还介绍了如何对项目结构进行优化,以适应代码库的增长和复杂性,并重新设计了课程数据模型,添加了导师信息管理功能。

weixin_26805451的博客 809

innovus 命令每日精要 | 掌控Innovus布线的利器——setNanoRouteMode详解

在数字IC后端设计的复杂世界里,布线优化是至关重要的一步。今天,我来给大家深入讲解Innovus工具中setNanoRouteMode命令的精妙之处,让你轻松驾驭布线策略,提升设计质量。setNanoRouteMode是Innovus中用于配置NanoRoute绕线行为的关键命令。通过其丰富的参数,你可以精细控制布局后阶段的绕线策略、信号完整性优化、工艺适配及设计规则修复等流程。下面,我将按功能分类总结其核心选项,并针对不同场景给出建议。

weixin_50820814的博客 3532

Rust 全栈开发:从零到一,你该学哪些核心技术?

Rust 全栈不是未来,而是正在发生的现实。后端服务;前端 Web;桌面与 WASM;甚至命令行与云原生工具——你就拥有了完整的开发控制力。如果你想成为新一代的“全栈开发者”,Rust 是最值得你深入学习的语言之一。

未来已来,AI时代,学AI编程,做AI量化,就来大鹏AI教育。 1001

PCIe ATS介绍

主机侧使用IOMMU完成设备地址到物理memory地址的转换,以及设备访问权限的检查。但如果所有PCIe设备都在进行DMA操作,则TA(Translation Agent)和ATPT(Address Translation and Protection Table)则会成为瓶颈,从而影响系统的latency。

maxwell2ic的博客 6024

Axum-Yew 全栈 Rust Web 应用项目教程

Axum-Yew 全栈 Rust Web 应用项目教程 1. 项目介绍 axum-yew-setup 是一个开源项目,旨在为开发者提供一个快速启动的模板,用于构建全栈 Rust Web 应用程序。该项目结合了 axum 和 yew 两个强大的 Rust 库,axum 是一个高性能的 Web 框架,而 yew 是一个用于构建 Web 前端的 Rust 框架。通过这个项目,开发者可以轻松地搭建一个前后...

gitblog_00487的博客 1261

ArcMap投影变换避坑指南:为什么你的坐标转换总出错?常见问题解析与解决方案

本文深入解析ArcMap中坐标转换与投影变换的核心区别与常见陷阱。针对坐标转换总出错的问题,从混淆“定义投影”与“投影变换”、栅格数据重采样选择、矢量数据地理变换参数设置等关键环节,提供清晰的避坑指南与实战解决方案,帮助用户确保空间数据的精确匹配。

weixin_29210727的博客 357

从零到一:STM32 CubeMX与WS2812B的DMA驱动艺术

本文详细介绍了如何使用STM32 CubeMX和DMA技术驱动WS2812B RGB LED灯条,从硬件设计到软件实现的全过程。通过CubeMX配置定时器和DMA,实现高效的PWM波形生成与数据传输,解决传统GPIO控制资源占用高的问题。文章还提供了颜色编码、动画效果实现及常见问题解决方案,助力开发者快速掌握智能LED控制技术。

weixin_28278377的博客 980

MoonZoon错误处理最佳实践:构建健壮Rust全栈应用的完整指南

MoonZoon作为Rust全栈框架,提供了全面的错误处理机制帮助开发者构建可靠应用。本文将系统介绍MoonZoon中的错误处理策略、最佳实践和实用技巧,让你的应用在面对异常时依然保持稳定运行。 ## 错误处理基础:认识MoonZoon的错误类型 MoonZoon框架定义了多种特定领域的错误类型,覆盖从网络通信到数据存储的各个方面。这些错误类型遵循Rust的错误处理哲学,既提供了详细的错误信息

gitblog_01132的博客 1042

如何绘制电气绝缘图(GB9706.1-2007和GB9706.1-2020差异)

是用来描述要考虑设备的绝缘状况和它们的值 ,从而便于和相关部门交流和沟通,如权威机构和检测实验室等。本文为绝缘图的实例, 包括所有相关的绝缘路径以及介电强度,爬电距离和电气间隙的值。

学海无涯的专栏 1万+

Rust全栈开发实战:PostgreSQL与Rust集成指南

在现代Web应用开发中,数据库是核心组件之一。本文将详细介绍如何在Rust全栈项目中使用PostgreSQL数据库,从基础安装到与Rust生态工具链的集成,为开发者提供一条清晰的技术路径。 ## 技术栈概述 Rust全栈开发通常遵循以下工作流程: 1. 数据库选型与安装(如PostgreSQL) 2. 使用原生SQL命令行工具测试 3. 集成ORM框架(如Diesel) 4. 构建Rust

gitblog_01172的博客 716

AgentScope实战训练营-Java开发HITL人机协作AI应用完整指南

本文手把手带你从零搭建一个基于 Spring Boot WebFlux + AgentScope + 通义千问的人机协作(HITL)AI 聊天应用。项目涵盖流式对话、工具调用、高危操作确认、对话中断、动态 MCP 工具接入、中英文双语界面等完整功能。文章从环境准备、pom.xml 配置、DTO 数据模型、Hook 机制、AgentService 核心服务、ChatController 接口到前端 HTML/CSS/JS 实现,逐一讲解每行代码的设计意图,并附带 REST API 接口说明、测试场景、常见问题

program哲学 713

Floyd (弗洛伊德)算法简述

Floyd在1962年由Robert Floyd以其当前公认的形式出版。算法作为三个嵌套for循环的现代公式首先由Peter Ingerman在1962年描述。Floyd 算法是解决图论问题的比较经典的算法,是解决给定的加权图中顶点间的最短路径的一种算法,可以正确处理有向图的最短路径问题。

慕羽★的博客 2万+

Rust Web开发常用库

本集合中所有库都是在开源项目中广泛使用且在2024年积极维护的库,排名靠前的库是当前使用比较广泛的,不全面但够用。

weixin_62799021的博客 2036

C#里使用NModbus来创建一个TCP从站服务

摘要:本文介绍了一个用C#实现的Modbus TCP从站服务器,基于.NET Framework 4.6.1开发。代码使用NModbus库创建TcpListener和ModbusSlaveNetwork,支持设置IP地址、端口号和从站ID。服务器实现了数据存储初始化功能(包括线圈和保持寄存器),并提供了启动/停止操作的UI界面和日志记录功能。该解决方案适用于需要调试Modbus TCP协议的场景,特别适合无法升级到更高版本.NET Framework的环境。

大坡3D软件开发 480

Rust 和 Rocket Web 开发(一)

Rocket 是 Rust 编程语言中第一个 Web 框架之一。Rocket 提供了构建 Web 应用程序的完整工具,例如请求路由工具、传入请求的强类型以及用于操作传入请求和传出响应的中间件。Rocket 还提供了模板支持和连接到各种数据库的功能。Rocket 是用 Rust 编程语言编写的 Web 框架。作为较新的编程语言之一,Rust 被设计为性能和安全性高。它易于创建安全、多线程和异步的应用程序。Rust 在工具、文档和社区包方面也有坚实的基础。

龙哥盟 1913

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Rust Web开发框架对比:Warp与Actix-web

Warp是一个基于异步编程的轻量级Web框架,构建在高性能的异步运行时Tokio之上。Warp的核心理念是Filter(过滤器),通过组合不同的过滤器来构建Web应用。主要特点类型安全且可组合的过滤器系统内置WebSocket支持友好的错误处理机制简洁的API设计Actix-web是一个功能丰富、高性能的Web框架,同样基于Tokio运行时。它采用了Actor模型,擅长处理高并发和复杂的异步操作。主要特点基于Actor模型的并发处理丰富的中间件支持强大的生态系统优异的性能表现。

Dontla的博客 2943

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

tower-web错误处理最佳实践:构建健壮的Rust Web应用

tower-web是一个快速、无样板代码的Rust Web框架,为开发者提供了高效构建Web应用的能力。在开发Web应用过程中,错误处理是确保应用稳定性和用户体验的关键环节。本文将分享tower-web框架中错误处理的最佳实践,帮助你构建更加健壮的Rust Web应用。 ## 了解tower-web的错误类型体系 tower-web提供了完善的错误类型体系,位于[src/error.rs](h

gitblog_00775的博客 771

Leptos与Axum集成:构建全栈Rust应用的最佳组合

在Rust生态系统中构建全栈Web应用时,选择合适的框架组合至关重要。Leptos作为现代化的前端框架,与Axum这一高性能Web框架的结合,为开发者提供了前所未有的开发体验和性能优势。 **读完本文你将掌握:** - Leptos与Axum集成的核心原理 - 完整的全栈Rust应用搭建流程 - 服务器函数(Server Functions)的实现与使用 - 路由配置与状态管理的最佳实践 - 生...

gitblog_00009的博客 1091

Rust Web 中的错误处理与响应构建全视角

code: u16,每个错误指定 HTTP 状态码;返回 JSON;业务信息可通过提供。错误处理和响应构建是 Rust Web 服务的灵魂部分:它连接着业务、安全、用户体验、运维同时考虑。Rust 的类型系统为我们提供了“强类型+明确语义”的工具,也要求我们在设计之初就思考错误分类、响应结构、上下文传递与观察能力。

weixin_39287383的博客 991

Rust Web开发指南 第一章(Axum 服务器基础)

摘要:Rust在Web开发领域展现出独特优势,凭借内存安全机制、高性能执行效率、完善的异步IO模型等特性,成为构建高并发、高可靠性Web服务的理想选择。文章详细分析了Rust相较于Java/Python等语言的技术优势,并重点介绍了Axum框架的特点与开发实践,包括路由配置、错误处理和优雅关闭等核心功能实现。通过具体示例展示了如何从零开始搭建一个具备生产级可靠性的Rust Web应用,为开发者提供了实用的技术参考。

北京锋通科技有限公司的技术blog 1877

Rust语言的Web开发

Rust是一种由Mozilla研究院开发的系统编程语言,首次发布于2010年。它的设计目标是帮助开发者构建快速且安全的系统,尤其是在并发和内存管理方面。Rust在内存安全和数据竞争方面采用了独特的所有权系统,从根本上减少了运行时错误的可能性。内存安全:通过所有权、借用和生命周期机制,Rust能够在编译时检查内存的使用情况,防止常见的内存错误如悬空指针、双重释放等。高性能:Rust的性能可与C和C++媲美,在需要高性能和低延迟的场景中表现优异。并发支持。

2501_90425705的博客 489

【跟小嘉学 Rust 编程】三十三、Rust的Web开发框架之一: Actix-Web的基础

本章节讲解 Rust的Web开发框架的介绍和对比。Actix Web、Axum、Rocket、Warp、Tide、Poem、Pavex、Hyper等框架。主要教材参考 《The Rust Programming Language》主要教材参考 《Rust For Rustaceans》主要教材参考 《The Rustonomicon》主要教材参考 《Rust 高级编程》主要教材参考 《Cargo 指南》主要教材参考 《Rust 异步编程》主要教材参考 《Rust 设计模式》

小嘉丶学长的博客 4542
上一篇: Rust Web 全栈开发(八):添加功能并重构
下一篇: Rust Web 全栈开发(九):增加教师管理功能
UestcXiye
博客等级 码龄8年 9031粉丝 1306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值