rust程式設計(3)結構體相關概念和疑問

来源:https://www.cnblogs.com/azoux/archive/2023/11/13/17830577.html
-Advertisement-
Play Games

結構體 // 如何定義結構體 struct User { active: bool, username: String, email: String, sign_in_count: u64, } // 如何使用結構體 let user = User { active: true, username: ...


結構體

// 如何定義結構體
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}
// 如何使用結構體
let user = User {
	active: true,
  username: String::from("someusername123"),
  email: String::from("[email protected]"),
  sign_in_count: 1,
}
// 解構
// 這裡有個需要註意的是,如果某個類型沒有實現Copy trait
// 那麼就會傳遞所有權,比如這裡的email,所以在定義完user2以後,user變數就不能再使用了
// 如果我們額外傳入了email,那麼user就還能使用
// 另一個問題:結構的位置會影響最後的值嗎?就像js的對象結構,我們可以在下麵覆蓋掉上面解構對象的某些屬性
// 在Rust中,結構(destructuring)不是用來“覆蓋”值的,而是用來“重組”已存在的值到一個新的變數。這跟JavaScript的對象解構賦值不同,後者允許你在解構的同時覆蓋之前對象的屬性。
/**
好的,想象一下你有一個玩具箱子,裡面有很多玩具。現在你想要一個新的箱子,而且你想把除了最愛的小黃鴨之外的所有玩具都放進新箱子里。在Rust中,我們可以用一個特殊的魔法詞“..”,告訴大人我們想這麼做。
所以我們對大人說:“請把我的所有玩具,除了小黃鴨,都移到新的箱子里去。”大人就會幫你做這件事。但是一旦玩具移到了新箱子里,你就不能再從舊箱子里拿玩具了,因為它們已經不在那裡了。這就像當你把玩具借給朋友後,你就不能再玩那些借出去的玩具了。
而且,你不能像在畫畫時那樣,先畫一個太陽,然後又在上面畫一個大風箏蓋住太陽。在Rust里,一旦你把玩具放到了新箱子,你就決定好了誰去了新箱子,不能改變主意了。
這樣的魔法規則幫助確保你的玩具箱子井井有條,每個玩具都知道它應該在哪個箱子里,就像確保你的房間整潔一樣。這樣你就不會弄丟玩具,也能更容易找到想玩的玩具。
*/
let user2 = User {
	username: String::from("hahaha"),
	...user
}

// rust的整個結構體實例都必須是可變的,才能修改其中的屬性,rust不允許只有某些屬性是可變的

// build_user 函數返回的User實例,是可變的嗎
/**
在Rust中,可變性是由變數的綁定決定的,而不是由函數返回的值決定的。
這意味著,當你的build_user函數返回一個User實例時,它返回的是一個不可變的User實例。
如果你想要修改這個User,你需要在使用它的地方將它綁定到一個可變變數上。
*/
fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username: username,
        email: email,
        sign_in_count: 1,
    }
}

rust的可不可變是針對變數而不是值的嗎?

正是如此!在Rust的世界里,可變性(mutability)是關於變數綁定,而不是值本身。想象一下,你的玩具可以放在兩種不同的箱子里:一個是用膠帶封死的箱子(不可變的),另一個是可以隨時打開加東西的箱子(可變的)。玩具(值)本身沒變,但根據你放它的箱子的類型,你可能可以改變箱子里的玩具集合。

所以,在Rust中,當你聲明一個變數時,你可以選擇它是不是mut的,就是選擇用哪種箱子。一旦你決定了,只有mut箱子里的玩具(值)才能被換掉或者修改。如果你試圖改變一個用膠帶封死的箱子里的玩具,Rust會阻止你,確保你不會意外地弄亂你的玩具集合。這個規則是Rust確保程式安全的方式之一,避免了數據在你不知情的情況下被更改。

這樣的設計讓Rust程式的行為變得非常可預測,並且減少了程式中出現錯誤的機會。而且,這還幫助Rust管理記憶體,因為它可以確切地知道何時某個值不再被需要,以及何時它可以被安全地回收或重新使用。

元組結構體

// 註意,Color和Point是不同的類型,即使其中的元素個數和類型一樣
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

沒有任何欄位的類單元結構體

沒有任何欄位的類單元結構體有什麼用呢?

好比是小朋友的想象游戲,有時候你會拿個香蕉當電話玩,對吧?雖然它就是個香蕉,但在你的游戲里它就變成了電話。在Rust的世界里,一個沒有任何欄位的結構體就像是那個香蕉電話,它本身沒啥用,但你給它賦予了意義。

就像你可以想象香蕉是電話一樣,程式員有時需要一些東西來代表某些特別的事情,即使那個東西本身什麼都沒有。比如說,我們可能有一個空的結構體來表示游戲中的一個事件,它本身不保存任何信息,但它的存在就代表了某個事件發生了。

還有,就像你玩耍時可能會用一個看不見的"盒子"來裝你想象中的寶貝一樣,程式員也可能會用這種結構體來做出某些選擇。例如,它們可以用來打開或關閉軟體的某些功能,就像是開關一樣。

另外,這種結構體也像是游戲規則里的“它”,比如“你是它”游戲中的“它”。它代表了一個標記或者一個特定的角色,即使它自己沒有任何東西。

所以,即使是空空如也的結構體,在Rust這個大型游戲中也有自己的角色和用途。這就是它們的魔法之處!

讓我們來看一個Rust中的代碼例子,這個例子里我們將使用一個沒有任何欄位的結構體來做一些有趣的事情。想象一下,我們有一個游戲,游戲里有一些特殊的時刻,比如“游戲開始”或“游戲結束”。我們可以用不同的結構體來代表這些時刻,哪怕這些結構體裡面什麼都沒有!

這裡有一個小小的代碼片段:

// 定義一個沒有欄位的結構體,叫做 `GameEvent`。
struct GameStart; // 游戲開始事件
struct GameEnd; // 游戲結束事件

// 我們可以定義一個函數來處理游戲事件。
// 註意這個函數如何接受不同的事件結構體作為參數。
fn process_game_event(event: impl GameEventTrait) {
    // 在這個函數里,我們可以根據事件的類型來做不同的事情。
    event.print_details();
}

// 讓我們為這個結構體實現一個Trait,這個Trait允許我們列印出事件的細節。
trait GameEventTrait {
    fn print_details(&self);
}

// 實現 'GameStart' 結構體的 'GameEventTrait'。
impl GameEventTrait for GameStart {
    fn print_details(&self) {
        println!("The game has started!");
    }
}

// 實現 'GameEnd' 結構體的 'GameEventTrait'。
impl GameEventTrait for GameEnd {
    fn print_details(&self) {
        println!("The game has ended!");
    }
}

// 現在我們可以創建這些事件的實例並處理它們。
let start = GameStart;
let end = GameEnd;

// 處理這些事件
process_game_event(start);
process_game_event(end);

在這個例子中,我們定義了兩個沒有任何欄位的結構體:GameStartGameEnd。它們都實現了一個叫做 GameEventTrait 的trait,這個trait有一個方法 print_details,用於輸出一個關於事件的消息。

然後我們有一個 process_game_event 函數,它接受任何實現了 GameEventTrait 的類型的實例。這意味著我們可以傳入 GameStartGameEnd 的實例。

當我們調用這個函數並傳入 GameStartGameEnd 的實例時,它會列印出相應的開始或結束游戲的消息。

這樣的結構體很適合用於事件處理、狀態機、消息傳遞等場景,在這些場景中,標記或者控制流的存在比持有數據更重要。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、創建Date對象 var dateObj=new Date(); var now = Date.now() 當前時間 二、Date方法 1、將日期轉為字元串 toLocaleString() toLocaleDateString() toLocaleTimeString() 2、獲取年、月、日、 ...
  • 本文介紹了結構型設計模式中的代理設計模式,講解了靜態代理、JDK的動態代理和cglib的動態代理,並用代碼進行演示。 ...
  • 趁著雙十一備戰封板,終於又有一些時間可以梳理一下最近的心得。最近這半年跟同事討論比較多的是分層架構,然後就會遇到兩個觸及靈魂的問題,一個是如何做好分層架構,二是DDD在架構層面該如何落地。 ...
  • 一、定義 給某一個對象提供一個代理或占位符,並由代理對象控制對原對象的訪問。代理模式是一種結構型模式。 二、描述 代理模式的結構比較簡單,其核心是代理類,為了讓客戶端能夠一致性地對待真實對象和代理對象,在代理模式中引入了抽象層。包含以下三個角色: 1、Subject(抽象主題角色):它聲明真實主題和 ...
  • 清晰架構原則對於任何希望創建健壯、可維護和可擴展軟體的軟體開發者來說都至關重要。理解並實施這些概念可以顯著提升你的編程技能。以下是對20個基本架構洞見的深入探討:依賴規則: 清晰架構的核心是依賴規則。它規定源代碼的依賴關係應始終指向內部。這種內向的方向確保了一個具有彈性的基礎,強調了關註點的分離,並 ...
  • 話不多說,今天我們要介紹的是函數。本系列文章追求短而精,今天我們將重點討論函數以及與Java方法的區別。與Java方法不同,函數不需要像Java方法一樣講究修飾符等其他特性,它只需要使用"def"關鍵字進行聲明。另外,函數的參數也與Java方法有所不同,Java方法中不存在預設參數的概念,而在Pyt... ...
  • 七、判斷(二) 引:學校舉辦了一個抽獎獲得,根據學號給予學生獎勵,學生獎勵如下: 學號 獎勵 15692 現金500 65432 現金450 98741 現金250 2531 現金150 666 學號*2 321 學號*2 //if語句實現 #include <iostream> int main( ...
  • 在現代互聯網時代中,功能變數名稱是我們上網必備的工具,它承載著我們上網所需的所有信息。但是有時我們需要瞭解功能變數名稱的相關信息,比如IP地址、註冊人信息、功能變數名稱到期時間等等。這時候,我們就需要用到功能變數名稱反查API介面,來獲取這些信息。 一鍵獲取功能變數名稱的相關信息——功能變數名稱反查API介面的神奇功能,可以幫助我們快速獲取我們所 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...