ホームページ > バックエンド開発 > Golang > xybor-x/enum を使用した Go Enum の問題と解決策

xybor-x/enum を使用した Go Enum の問題と解決策

DDD
リリース: 2024-12-19 18:44:11
オリジナル
875 人が閲覧しました

列挙型とは何ですか?

列挙型 (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 は enum をネイティブにサポートしていません。ただし、Go で enum を定義する一般的な方法は、iota アプローチを使用することです。

package main

type TrafficLight int

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

func main() {
    fmt.Println(RED) // Output: 0
}
ログイン後にコピー

ただし、この方法で enum を扱う場合、いくつかの問題があります。

  • 組み込みメソッドの欠如: すべての列挙型値のリストや文字列と列挙型間の変換などの機能は直接サポートされていません。
  • 制限された型安全性: 列挙型は通常、基本型 (int や string など) を使用して表現されるため、意図しない代入のリスクが増加します。
  • シリアル化と逆シリアル化の複雑さ: 列挙型と JSON などの形式間のマッピングには追加の処理が必要です。

xybor-x/enum ライブラリ

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

xybor-x/enum ライブラリは、コード生成を行わずに、エレガントで使いやすく、強力な Go enum ソリューションを提供します。

xybor-x/enum で使用できる enum の種類がいくつかあります。最適なものを選択してください。

基本的な列挙型

長所?

  • シンプルです。
  • 定数値をサポートします。

短所?

  • 組み込みメソッドはありません。
  • 型安全性はありません。
  • シリアル化と逆シリアル化のサポートがありません。 従来の列挙型と同様、基本的な列挙型には組み込みメソッドがありません。ただし、xybor-x/enum のユーティリティ関数を使用して、このタイプの 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"
}
ログイン後にコピー

WrapEnum

長所?

  • 定数値をサポートします。
  • 多くの便利な組み込みメソッドを提供します。
  • すぐに使える完全なシリアル化と逆シリアル化のサポート。

短所?

  • 基本的なタイプの安全性のみを提供します。
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

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
ベトナム語のビブロ: https://viblo.asia/p/cac-van-de-cua-go-enum-va-cach-giai-quyet-voi-xybor-xenum-Yym401A9J91

以上がxybor-x/enum を使用した Go Enum の問題と解決策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート