AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

一起聊聊在Rust中使用枚舉表示狀態

來源: 責編: 時間:2024-04-07 17:05:54 198觀看
導讀許多具有系統編程背景的Rust初學者傾向于使用bool(甚至u8—8位無符號整數類型)來表示“狀態”。例如,如何使用bool來指示用戶是否處于活動狀態?struct User { // ... active: bool,}一開始,這可能看起來不錯,但是隨

許多具有系統編程背景的Rust初學者傾向于使用bool(甚至u8—8位無符號整數類型)來表示“狀態”。8Nh28資訊網——每日最新資訊28at.com

例如,如何使用bool來指示用戶是否處于活動狀態?8Nh28資訊網——每日最新資訊28at.com

struct User {    // ...    active: bool,}

8Nh28資訊網——每日最新資訊28at.com

一開始,這可能看起來不錯,但是隨著代碼庫的增長,會發現“active”不是二進制狀態。用戶可以處于許多不同的狀態,用戶可能被掛起或刪除。但是,擴展User結構體可能會出現問題,因為代碼的其他部分有可能依賴active是bool類型。8Nh28資訊網——每日最新資訊28at.com

另一個問題是bool不是自文檔化的。active = false是什么意思?用戶是否處于非活動狀態,或者用戶被刪除了,或者用戶被掛起了?我們不知道!8Nh28資訊網——每日最新資訊28at.com

或者,可以使用一個無符號整數來表示狀態:8Nh28資訊網——每日最新資訊28at.com

struct User {    // ...    status: u8,}

8Nh28資訊網——每日最新資訊28at.com

這稍微好一點,因為我們現在可以使用不同的值來表示更多的狀態:8Nh28資訊網——每日最新資訊28at.com

const ACTIVE: u8 = 0;const INACTIVE: u8 = 1;const SUSPENDED: u8 = 2;const DELETED: u8 = 3;let user = User {    // ...    status: ACTIVE,};

8Nh28資訊網——每日最新資訊28at.com

u8的一個常見用例是與C代碼交互,在這種情況下,使用u8似乎是唯一的選擇。我們還可以將u8包裝在一個新類型中!8Nh28資訊網——每日最新資訊28at.com

struct User {    // ...    status: UserStatus,}struct UserStatus(u8);const ACTIVE: UserStatus = UserStatus(0);const INACTIVE: UserStatus = UserStatus(1);const SUSPENDED: UserStatus = UserStatus(2);const DELETED: UserStatus = UserStatus(3);let user = User {    // ...    status: ACTIVE,};

8Nh28資訊網——每日最新資訊28at.com

這樣我們就可以在UserStatus上定義方法:8Nh28資訊網——每日最新資訊28at.com

impl UserStatus {    fn is_active(&self) -> bool {        self.0 == ACTIVE.0    }}

8Nh28資訊網——每日最新資訊28at.com

我們甚至還可以定義一個構造函數來驗證輸入:8Nh28資訊網——每日最新資訊28at.com

impl UserStatus {    fn new(status: u8) -> Result<Self, &'static str> {        match status {            ACTIVE.0 => Ok(ACTIVE),            INACTIVE.0 => Ok(INACTIVE),            SUSPENDED.0 => Ok(SUSPENDED),            DELETED.0 => Ok(DELETED),            _ => Err("Invalid status"),        }    }}

8Nh28資訊網——每日最新資訊28at.com

8Nh28資訊網——每日最新資訊28at.com

使用枚舉表示狀態

8Nh28資訊網——每日最新資訊28at.com

枚舉是為域內的狀態建模的好方法。它們以一種非常簡潔的方式表達你的意圖。8Nh28資訊網——每日最新資訊28at.com

#[derive(Debug)]pub enum UserStatus {    /// 用戶是活躍的,可以完全訪問他們的帳戶和任何相關功能。    Active,    /// 用戶的帳戶處于非活動狀態。該狀態可由用戶或管理員恢復為激活狀態。    Inactive,     /// 該用戶的帳戶已被暫時暫停,可能是由于可疑活動或違反政策。    /// 在此狀態下,用戶無法訪問其帳戶,并且可能需要管理員的干預才能恢復帳戶。    Suspended,    /// 該用戶的帳號已被永久刪除,無法恢復。    /// 與該帳戶關聯的所有數據都可能被刪除,用戶需要創建一個新帳戶才能再次使用該服務。    Deleted,}

8Nh28資訊網——每日最新資訊28at.com

我們可以將這個枚舉插入到User結構體中:8Nh28資訊網——每日最新資訊28at.com

struct User {    // ...    status: UserStatus,}

8Nh28資訊網——每日最新資訊28at.com

但這還不是全部。在Rust中,枚舉比許多其他語言強大得多。例如,可以向枚舉變量中添加數據:8Nh28資訊網——每日最新資訊28at.com

#[derive(Debug)]pub enum UserStatus {    Active,    Inactive,    Suspended { until: DateTime<Utc> },    Deleted { deleted_at: DateTime<Utc> },}

8Nh28資訊網——每日最新資訊28at.com

我們還可以表示狀態轉換:8Nh28資訊網——每日最新資訊28at.com

use chrono::{DateTime, Utc};#[derive(Debug)]pub enum UserStatus {    Active,    Inactive,    Suspended { until: DateTime<Utc> },    Deleted { deleted_at: DateTime<Utc> },}impl UserStatus {    /// 暫停用戶直到指定日期    fn suspend(&mut self, until: DateTime<Utc>) {        match self {            UserStatus::Active => *self = UserStatus::Suspended { until },            _ => {}        }    }    /// 激活用戶    fn activate(&mut self) -> Result<(), &'static str> {        match self {            // A deleted user can't be activated!            UserStatus::Deleted { .. } => return Err("can't activate a deleted user"),            _ => *self = UserStatus::Active        }        Ok(())    }    /// 刪除用戶,這是一個永久的動作!    fn delete(&mut self) {        if let UserStatus::Deleted { .. } = self {            // 已經刪除,不要再設置deleted_at字段。            return;        }        *self = UserStatus::Deleted {            deleted_at: Utc::now(),        }    }    fn is_active(&self) -> bool {        matches!(self, UserStatus::Active)    }    fn is_suspended(&self) -> bool {        matches!(self, UserStatus::Suspended { .. })    }    fn is_deleted(&self) -> bool {        matches!(self, UserStatus::Deleted { .. })    }}#[cfg(test)]mod tests {    use chrono::Duration;    use super::*;    #[test]    fn test_user_status() -> Result<(), &'static str>{        let mut status = UserStatus::Active;        assert!(status.is_active());        // 暫停到明天        status.suspend(Utc::now() + Duration::days(1));        assert!(status.is_suspended());        status.activate()?;        assert!(status.is_active());        status.delete();        assert!(status.is_deleted());        Ok(())    }    #[test]    fn test_user_status_transition() {        let mut status = UserStatus::Active;        assert!(status.is_active());        status.delete();        assert!(status.is_deleted());        // 無法激活已刪除的用戶        assert!(status.activate().is_err());    }}

8Nh28資訊網——每日最新資訊28at.com

看看我們僅僅用幾行代碼就涵蓋了多少內容!我們可以放心地擴展應用程序,因為我們知道不會意外地刪除用戶兩次或重新激活已刪除的用戶。非法的狀態轉換現在是不可能的!8Nh28資訊網——每日最新資訊28at.com

8Nh28資訊網——每日最新資訊28at.com

8Nh28資訊網——每日最新資訊28at.com

使用枚舉與C代碼交互

C代碼:8Nh28資訊網——每日最新資訊28at.com

typedef struct {    uint8_t status;} User;User *create_user(uint8_t status);

8Nh28資訊網——每日最新資訊28at.com

你可以寫一個Rust枚舉來表示狀態:8Nh28資訊網——每日最新資訊28at.com

#[repr(u8)]#[derive(Debug, PartialEq)]pub enum UserStatus {    Active = 0,    Inactive,    Suspended,    Deleted,}impl TryFrom<u8> for UserStatus {    type Error = ();    fn try_from(value: u8) -> Result<Self, Self::Error> {        match value {            0 => Ok(UserStatus::Active),            1 => Ok(UserStatus::Inactive),            2 => Ok(UserStatus::Suspended),            3 => Ok(UserStatus::Deleted),            _ => Err(()),        }    }}

8Nh28資訊網——每日最新資訊28at.com

注意到#[repr(u8)]屬性了嗎?它告訴編譯器將此枚舉表示為無符號8位整數。這對于與C代碼的兼容性至關重要。8Nh28資訊網——每日最新資訊28at.com

現在,讓我們用一個安全的Rust包裝器包裝C函數:8Nh28資訊網——每日最新資訊28at.com

extern "C" {    fn create_user(status: u8) -> *mut User;}pub fn create_user_wrapper(status: UserStatus) -> Result<User, &'static str> {    let user = unsafe { create_user(status as u8) };    if user.is_null() {        Err("Failed to create user")    } else {        Ok(unsafe { *Box::from_raw(user) })    }}

8Nh28資訊網——每日最新資訊28at.com

Rust代碼現在使用豐富的enum類型與C代碼通信。8Nh28資訊網——每日最新資訊28at.com

8Nh28資訊網——每日最新資訊28at.com

8Nh28資訊網——每日最新資訊28at.com

總結

Rust中的枚舉比大多數其他語言更強大。它們可以用來優雅地表示狀態轉換——甚至可以跨越語言邊界。8Nh28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-81736-0.html一起聊聊在Rust中使用枚舉表示狀態

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 探索并發安全的Go語言Map - 深入理解Cmap

下一篇: 你有思考過@Transactional事務是真的好用嗎?

標簽:
  • 熱門焦點
Top