---
title: "什麼是 Solidity 中的 struct？"
description: "了解 Solidity Struct 的作用、運作方式，以及何時該使用"
---

# 什麼是 Solidity 中的 struct？

[Solidity](https://www.alchemy.com/overviews/solidity) 中有不同的基本資料型別，例如 [_uint_（無符號整數）](https://www.alchemy.com/overviews/solidity-uint)、_bool_ 和 _string_，但身為區塊鏈開發者，你可能需要一種可以自行定義的彈性資料型別。**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](https://www.alchemy.com/overviews/solidity-compiler) 前面的型別是自訂型別
1. 為 struct 命名，此名稱會與 struct 內打包的變數相互對應
1. 使用大括號，因為其他形式的括號，例如方括號或圓括號，都無法編譯通過

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

<ImageBlock
  src="https://media.alchemy.com/1704181525-parsererror-message.png"
  alt="未在 struct 中使用大括號時，Remix 編譯器顯示的 ParserError 訊息。"
  width={809}
  height={185}
  caption="未在 struct 中使用大括號時，Remix 編譯器顯示的 ParserError 訊息。"
/>

      4. 宣告資料型別及其對應的變數

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

#### **開發者提示：**

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

### 如何宣告 Solidity struct

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

#### **在合約外部宣告 struct**

在上面的例子中，_floorOverlay_ struct 是在 [smart contract](https://www.alchemy.com/overviews/solidity-smart-contract) 外部宣告的，因此程式碼庫中的所有合約都可以呼叫它。若想建立一個適用於所有合約的通用 struct，而不是只適用於個別合約的專屬 struct，最好在智能合約外部宣告它。

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

#### **在合約內部宣告 struct**

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

### 如何匯入 Solidity struct

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

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

### **如何在 Solidity 中初始化 struct**

即使你已經宣告並建立了 struct，如果沒有為它指定初始值，你仍然無法在[各種 Solidity 函式](https://www.alchemy.com/overviews/solidity-modifier)中使用它。初始化 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](https://www.alchemy.com/overviews/solidity-mapping) 可以讓我們更容易追蹤 DAO 成員的地址，以及他們是否已經投票。

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

<ImageBlock
  src="https://media.alchemy.com/1704181857-remix-error.png"
  alt="嘗試將 struct 宣告為 key type 時，Remix 顯示的錯誤訊息。"
  width={935}
  height={160}
  caption="嘗試將 struct 宣告為 key type 時，Remix 顯示的錯誤訊息。"
/>

## **總結 — Solidity 中 struct 的本質是什麼？**

Solidity 中的 struct 讓開發者能夠建立適合自己所開發項目的自訂型別。這些自訂型別就像是能容納其他相關資料型別的容器。想進一步了解 struct，歡迎報名 [Alchemy University's Solidity bootcamp](https://www.alchemy.com/university/courses/solidity?a=53bceeeaa3)！
