跳至內容
0%

什麼是 Solidity 中的 struct?

發布於 2022年10月4日閱讀時間 2 分鐘

Solidity 中有不同的基本資料型別,例如 uint(無符號整數)boolstring,但身為區塊鏈開發者,你可能需要一種可以自行定義的彈性資料型別。struct 是 Solidity 中的一種資料結構格式,可以將不同資料型別的變數綁在一起,成為一個變數或自訂型別。

本文將介紹 Solidity 中的 struct,說明它們的作用與運作方式。最後,我們會說明如何用 struct 來建立更穩健的智能合約。

什麼是 Solidity struct?

struct 是 Solidity 中一種具創意的資料結構格式,可以將不同資料型別的變數綁在一起,成為一個變數或自訂型別。 一旦資料型別被歸納到一個 struct 中,struct 的名稱就代表其中的變數子集合。

可以把 struct 想像成裝有不同種類物品的容器,當你移動這個容器時,裡面的所有物品也會一起移動。因此,當 Solidity 開發者宣告或呼叫某個 struct 的名稱時,該 struct 會依照其中包含的資料型別做出對應的行為。

以下是一個 Solidity struct 的範例:

上面這個 struct 範例包含了 address creator、string name、address users,以及 uint amount 這些變數。

Solidity struct 程式碼範例

本節將展示如何在 Solidity 中定義並建立 struct 的範例程式碼。我們也會示範 struct 宣告的兩種方式。最後,我們會說明如何匯入並初始化 struct。

如何在 Solidity 中定義並建立 struct

struct 的程式碼寫法和 Javascript 中物件宣告的方式相似。雖然外觀相似,但語法運作方式不同。Solidity struct 一律遵循以下格式:

以下是定義並建立 Solidity struct 的方式:

  1. 使用 struct 關鍵字建立 struct,這會告訴 Solidity compiler 前面的型別是自訂型別
  2. 為 struct 命名,此名稱會與 struct 內打包的變數相互對應
  3. 使用大括號,因為其他形式的括號,例如方括號或圓括號,都無法編譯通過

如果你沒有使用大括號,會在 Remix 上產生以下的 ParserError 訊息。

未在 struct 中使用大括號時,Remix 編譯器顯示的 ParserError 訊息。
未在 struct 中使用大括號時,Remix 編譯器顯示的 ParserError 訊息。
  1. 宣告資料型別及其對應的變數

在上面的例子中,這些是 string theWord、uint theFigure,以及 bool polarData。這就是你宣告 struct 子集合的地方。struct 在智能合約中宣告完成後,我們就可以在後續程式碼中呼叫該 struct 的名稱。

開發者提示:

  • 只能使用大括號
  • struct 的每個成員結尾都要加上分號
  • 如果你宣告的資料型別和輸入的變數類別不符,Solidity 會拋出錯誤
  • 智能合約可以包含多個 struct,這些 struct 是由各自的關鍵字來區分的

如何宣告 Solidity struct

有兩個地方可以宣告 struct:合約內部或合約外部。你要在哪裡宣告 Solidity struct,取決於你想做什麼。讓我們來看看這兩種 struct 宣告方式。

在合約外部宣告 struct

在上面的例子中,floorOverlay struct 是在 smart contract 外部宣告的,因此程式碼庫中的所有合約都可以呼叫它。若想建立一個適用於所有合約的通用 struct,而不是只適用於個別合約的專屬 struct,最好在智能合約外部宣告它。

此外,如果你想讓多個智能合約使用同一組 struct 集合,應該緊接在 pragma 後面宣告,而不是在每個智能合約中各自分別建立 struct。

在合約內部宣告 struct

carpet struct 是宣告在智能合約內部的,因此該 struct 的作用範圍僅限於目前的合約,其他合約無法呼叫它的名稱。

如何匯入 Solidity struct

struct 可以從一個智能合約匯入到另一個智能合約,這有助於開發者節省時間並建立可重複使用的程式碼。為了示範如何匯入 struct,以下有兩個智能合約:一個是建立 struct 的合約,另一個則是匯入該 struct 的合約。

匯入時有一個要避免的錯誤:第二個合約的名稱必須與你想匯入的 struct 名稱相同。否則 Solidity compiler 將無法識別它,進而導致錯誤。

如何在 Solidity 中初始化 struct

即使你已經宣告並建立了 struct,如果沒有為它指定初始值,你仍然無法在各種 Solidity 函式中使用它。初始化 struct 有三種方式:(一)鍵值配對法、(二)先定義後更新法、(三)用括號包裝參數法。

1. 鍵值配對法

用這種方法時,你會選取 struct 中的每個鍵型別並為其賦值。

這種方法的語法並不嚴格;你不一定要照 struct 中型別的順序來寫。

2. 先定義後更新法

這種初始化方法的語法是,你要先輸入一個變數來儲存該 struct,之後再使用這個變數來存取並為 struct 的每個成員命名。以下程式碼即為示範:

不過要注意,大多數開發者不太使用這個方法,因為它比較冗長。

3. 用括號包裝參數法

如果你要用這個方法,就必須呼叫 struct 的名稱、儲存其記憶體,並依序為 struct 的成員賦值。以下是一個範例:

在這裡,「measles」是儲存此次初始化的變數,我們也依照 struct 中列出的順序宣告了參數。務必記得將宣告的名稱放在括號內並加上引號,這樣 Solidity compiler 才能識別它。

Solidity struct 使用情境

本節將示範一個使用 Solidity 追蹤合約內使用者資訊的情境。在這個情境中,struct 會被進行 mapping。

Solidity 中的 struct 可以進行 mapping 嗎?

struct 可以在 Solidity 中作為值型別(value type)進行 mapping,讓你能夠追蹤 struct 中任何成員的相關資訊。 舉例來說,可以看看以下程式碼:

在這個合約中,某個 DAO 中每個成員的資訊都被分類整理。我們在這裡建立了兩種 mapping:一種是簡單的,另一種是巢狀的。

在簡單的 mapping 中,我們把每個成員的地址對應到 struct 中,讓特定成員更容易被找到。此外,巢狀 mapping 可以讓我們更容易追蹤 DAO 成員的地址,以及他們是否已經投票。

由於 mapping 一律遵循「鍵型別 => 值型別」的語法,struct 必須一律宣告為值型別,而不是鍵型別,否則會出現錯誤。

嘗試將 struct 宣告為 key type 時,Remix 顯示的錯誤訊息。
嘗試將 struct 宣告為 key type 時,Remix 顯示的錯誤訊息。

總結 — Solidity 中 struct 的本質是什麼?

Solidity 中的 struct 讓開發者能夠建立適合自己所開發項目的自訂型別。這些自訂型別就像是能容納其他相關資料型別的容器。想進一步了解 struct,歡迎報名 Alchemy University's Solidity bootcamp

Background gradient

打造區塊鏈魔法

Alchemy 結合最強大的 Web3 開發者產品與工具,並提供資源、社群與卓越的支援。