首頁 > 後端開發 > Golang > Go Enum 與 xybor-x/enum 的問題及解決方案

Go Enum 與 xybor-x/enum 的問題及解決方案

DDD
發布: 2024-12-19 18:44:11
原創
844 人瀏覽過

什麼是枚舉?

枚舉(enumeration)的縮寫,是一種特殊的資料類型,表示一組命名值。它用於定義概念上相關的常數值的集合,提高程式碼可讀性並減少因使用任意文字值而導致的錯誤。

// Enum in Java
enum TrafficLight {
    RED, YELLOW, GREEN
}
登入後複製
登入後複製
# Enum in Python
from enum import Enum

class TrafficLight(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
登入後複製

Go 中的列舉

Go 本身不支援枚舉。然而,在 Go 中定義枚舉的流行方法是使用 iota 方法。

package main

type TrafficLight int

const (
    RED TrafficLight = iota // 0
    GREEN                   // 1
    BLUE                    // 2
)

func main() {
    fmt.Println(RED) // Output: 0
}
登入後複製

但是,以這種方式處理枚舉時存在一些問題:

  • 缺乏內建方法:不直接支援列出所有枚舉值或在字串和枚舉之間轉換等功能。
  • 有限型別安全:枚舉通常使用基本型別(例如 int 或 string)表示,這會增加意外分配的風險。
  • 序列化和反序列化複雜性:將枚舉映射到 JSON 等格式或從 JSON 等格式映射需要額外的處理。

xybor-x/enum 庫

Go Enum’s problems and solutions with xybor-x/enum

xybor-x/enum 函式庫為 Go 枚舉提供了優雅、易於使用且功能強大的解決方案,無需產生程式碼。

有一些類型的枚舉可以與 xybor-x/enum 一起使用,請選擇最合適的一種。

基本上枚舉

優點?

  • 簡單。
  • 支援常數值。

缺點?

  • 沒有內建方法。
  • 沒有型別安全。
  • 缺乏序列化和反序列化支持。 與傳統枚舉一樣,基本枚舉沒有內建方法。但是您可以使用 xybor-x/enum 的實用函數來處理這種類型的枚舉。
package main

type Role int

const (
    RoleUser Role = iota
    RoleAdmin
)

func init() {
    enum.Map(RoleUser, "user")
    enum.Map(RoleAdmin, "admin")

    // Optional: ensure no new enum values can be added to Role.
    enum.Finalize[Role]()
}

func main() {
    // Print the corresponding string.
    fmt.Println(enum.ToString(RoleUser)) // Output: user

    // Print out all valid enums.
    fmt.Println(enum.All[Role]())       // Output: [0 1]

    // Parse an enum from int.
    r1, ok := enum.FromInt[Role](1)
    fmt.Println(ok)                // Output: true
    fmt.Println(enum.ToString(r1)) // Output: admin

    // Parse an enum from string.
    r2, ok := enum.FromString[Role]("admin")
    fmt.Println(ok) // Output: true
    fmt.Println(r2) // Output: 1

    // Serialize json.
    data, err := enum.MarshalJSON(RoleUser)
    fmt.Println(err)          // Output: nil
    fmt.Println(string(data)) // Output: "user"
}
登入後複製

包裹枚舉

優點?

  • 支援常數值。
  • 提供了許多有用的內建方法。
  • 開箱即用的完整序列化和反序列化支援。

缺點?

  • 僅提供基本型別安全。
package main

// Only need to change the two following lines fromthe Basic enum.
type role any
type Role = enum.WrapEnum[role]

const (
    RoleUser Role = iota
    RoleAdmin
)

func init() {
    enum.Map(RoleUser, "user")
    enum.Map(RoleAdmin, "admin")

    // Optional: ensure no new enum values can be added to Role.
    enum.Finalize[Role]()
}

func main() {
    // Print the corresponding string. No need to use enum.ToString.
    fmt.Println(RoleUser) // Output: user

    // Print out all valid enums.
    fmt.Println(enum.All[Role]())       // Output: [user admin]

    // Parse an enum from int.
    r1, ok := enum.FromInt[Role](1)
    fmt.Println(ok) // Output: true
    fmt.Println(r1) // Output: admin

    // Parse an enum from string.
    r2, ok := enum.FromString[Role]("admin")
    fmt.Println(ok) // Output: true
    fmt.Println(r2) // Output: admin

    // Now you can use json.Marshal instead of enum.MarshalJSON.
    data, err := json.Marshal(RoleUser)
    fmt.Println(err)          // Output: nil
    fmt.Println(string(data)) // Output: "user"
}
登入後複製

WrapEnum 是最適合一般情況的枚舉。然而,它只提供基本的類型安全。如果您想要更嚴格的,請考慮使用 SafeEnum。

// WrapEnum cannot prevent this type of invalid declaration.
// Consider using SafeEnum.
r := Role(42)
登入後複製

安全枚舉

SafeEnum 定義了一個強型別型安全枚舉。與 WrapEnum 一樣,它提供了一組內建方法來簡化枚舉的使用。

SafeEnum 強制執行嚴格的型別安全,確保只允許預先定義的枚舉值。它可以防止意外創建新的枚舉類型,從而提供一組保證的有效值。

優點?

  • 提供強大的類型安全性。
  • 提供了許多有用的內建方法。
  • 開箱即用的完整序列化和反序列化支援。

缺點?

  • 不支援常數值。

為什麼持續支持很重要?

一些靜態分析工具(例如 bazel 的 nogo、具有詳盡擴展的 golangci-lint)支援檢查常數枚舉中的詳盡 switch 語句。透過選擇具有持續支援的枚舉,您可以在這些工具中啟用此功能。

// Enum in Java
enum TrafficLight {
    RED, YELLOW, GREEN
}
登入後複製
登入後複製

參考

xybor-x/enum:https://github.com/xybor-x/enum

中:https://medium.com/@huykingsofm/enum-handling-in-go-a2727154435e
越南語 viblo:https://viblo.asia/p/cac-van-de-cua-go-enum-va-cach-giai-quyet-voi-xybor-xenum-Yym401A9J91

以上是Go Enum 與 xybor-x/enum 的問題及解決方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板