enum

package module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 6 Imported by: 0

README

enum

Go Reference Go Version License

零依赖的类型安全枚举库,支持命名值集合、Struct 泛型反射构造,以及 Tree 递归多级下拉渲染。

快速开始

// 方式一:纯 Enum — 手写 Item 列表
var WeekdayEnum = enum.New(
    enum.ItemFrom("Monday", "周一", time.Monday),
    enum.ItemFrom("Tuesday", "周二", time.Tuesday),
    // ...
)

// 方式二:Struct — struct tag 反射构造
type Priorities struct {
    enum.Struct[Priority]
    Low    Priority `enum:"0,低"`
    Medium Priority `enum:"1,中"`
    High   Priority `enum:"2,高,disabled"`
}
p := enum.InitFor[Priority, Priorities]()

类型

Item[T] — 枚举成员
字段 类型 用途
key string 程序化标识,如 "UserCreated"
name string 展示名,如 "用户创建"
value T 枚举值 int/uint/string
disabled bool 是否禁用(仅展示,不可选)
ext map[string]string 扩展元数据

访问器: Key() Name() Value() IsDisabled() Ext()

构造: ItemFrom(key, name string, value T, opts ...ItemOption[T]) Item[T]

选项: WithDisabled[T]() WithExt[T](map[string]string)

Enum[T] — 枚举集合

有序、逻辑不可变(只有 ext 可写)。并发读安全;AddExt 修改 ext 元数据,不得与读操作并发(否则可能 concurrent map writes)。Struct[T].AddExt 同样受此约束。

方法 说明
ByKey(key) (Item[T], bool) 按 key 查找
MustByKey(key) Item[T] 按 key 查找,找不到 panic
ByValue(value) (Item[T], bool) 按 value 查找
MustByValue(value) Item[T] 按 value 查找,找不到 panic
Index(i) (Item[T], bool) 按位置索引
MustIndex(i) Item[T] 索引,越界 panic
Contains(value) bool 值是否存在
All() []Item[T] 所有成员(定义顺序)
Keys() []string 所有 key
Values() []T 所有 value
Len() int 成员数量
Range() iter.Seq2[string, Item[T]] Go 1.23 迭代器
AddExt(itemKey, extKey, extValue string) 添加扩展元数据
GetExt(itemKey) map[string]string 获取扩展元数据
ToMap() map[string]map[string]any 转为 map(前端 O(1) 查找)

JSON 序列化:

[
  {"key":"Low","name":"低","value":0},
  {"key":"Medium","name":"中","value":1},
  {"key":"High","name":"高","disabled":true,"value":2}
]
Struct[T] — struct tag 驱动构造

通过反射读 enum:"value,name[,disabled]" tag 自动构建:

type EventTopics struct {
    enum.Struct[string]
    UserCreated string `enum:"user.created,用户创建"`
    OrderPaid   string `enum:"order.paid,订单已付"`
}
events := enum.InitFor[string, EventTopics]()

// 字段即常量
switch topic { case events.UserCreated: ... }

// 通过 .Enum() 拿到 *Enum[string],所有 Enum 方法都可用
events.ByKey("UserCreated") // Item[string], true
events.All()                // []Item[string]
events.Enum().MarshalJSON() // JSON

⚠️ JSON 序列化注意:外层 struct 只要有自己的字段(不止嵌入 Struct[T]),Go 的 encoding/json 就会忽略内嵌的 MarshalJSON/UnmarshalJSON,序列化结果会是 {"enum":null,"UserCreated":""} 这种。此时必须显式用 .Enum()json.NewEncoder(w).Encode(events.Enum())

⚠️ UnmarshalJSON 只重建内部枚举:它更新 Enum 的数据,但不会更新外层 struct 的常量字段(events.UserCreated 等仍保持旧值)。反序列化后如需字段同步,请重新 InitFor

TreeNode / BuildTree / AsStringItems — 多级下拉

ext["parent"] 将平面列表转为递归树:

type Area int
type Areas struct {
    enum.Struct[Area]
    China     Area `enum:"101,中国"`
    Guangdong Area `enum:"102,广东"`
    Shenzhen  Area `enum:"103,深圳"`
}
areas := enum.InitFor[Area, Areas]()
areas.AddExt("Guangdong", enum.ParentExtKey, "101")
areas.AddExt("Shenzhen",  enum.ParentExtKey, "102")

tree := enum.BuildTree(areas.All())
// JSON:
// [{key:"China",name:"中国",value:"101",children:[
//   {key:"Guangdong",name:"广东",value:"102",children:[
//     {key:"Shenzhen",name:"深圳",value:"103"}
//   ]}
// ]}]

json.NewEncoder(w).Encode(tree)

异构枚举合并:

all := append(enum.AsStringItems(cats.All()), enum.AsStringItems(prods.All())...)
tree := enum.BuildTree(all)

常量

常量 用途
ParentExtKey "parent" BuildTree 的 ext key
NameKey "name" ToMap 的展示名字段
ValueKey "value" ToMap 的值字段
DisabledKey "disabled" 禁用字段
ExtKey "ext" 扩展元数据字段

枚举值类型约束

EnumBase 支持:

~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~string

自定义类型只要底层是 int/uint/string 即可(type Status int 等)。

多级下拉示例

水果 ──┬── 苹果
       └── 香蕉
蔬菜 ──── 胡萝卜
prods.AddExt("Apple",  enum.ParentExtKey, "FRUIT")
prods.AddExt("Banana", enum.ParentExtKey, "FRUIT")
prods.AddExt("Carrot", enum.ParentExtKey, "VEGETABLE")

添加新领域枚举

// 1. 定义类型
type MyEnum int
type MyEnums struct {
    enum.Struct[MyEnum]
    Alpha MyEnum `enum:"0,阿尔法"`
    Beta  MyEnum `enum:"1,贝塔"`
}

// 2. 初始化
e := enum.InitFor[MyEnum, MyEnums]()

// 3. 使用
switch v {
case e.Alpha:
case e.Beta:
}

配合 lint 工具(只读保护)

enum.InitFor 返回的结构体字段是导出的,运行期可以被改写(如 Events.UserCreated = "x"), 破坏枚举的只读语义。配套 lint 工具(lint,包 lint/,CLI cmd/enumlint/) 用静态分析扫描整个模块,找出所有对枚举变量或其字段的写入,把这类 bug 挡在提交前。

运行
# 在模块根目录(有 go.mod 的地方)
go run ./cmd/enumlint/ ./...
# 或安装为全局命令
go install github.com/donnol/enum/cmd/enumlint@latest && enumlint ./...

指定 enum 包路径:工具会自动发现声明 InitFor 的包;若 enum 是外部依赖且自动发现不到, 用 -enum-pkg 显式指定:

go run ./cmd/enumlint/ -enum-pkg github.com/donnol/enum ./...

若显式指定的 -enum-pkg 在扫描范围内找不到(既不是被扫描的包,也没有任何扫描文件 import 它), 会向 stderr 输出一条警告,提示检查 -enum-pkg 是否输入错误;此时不会误报违规,但值得核实。 无违规:exit 0,输出 ✅ enum check is good 🌟

发现违规:exit 1,输出违规表格(路径:行号 可直接点击跳转):

🚨 enum check is bad 💥
Location                          Kind   Target
--------                          ----   ------
server/biz/order/foo.go:6         field  event.Events.UserCreated
server/biz/order/foo.go:20        variable  Events
⚠️  请修正后重试!
检测规则
  • 只追踪包级 var X = enum.InitFor[T, struct{...}]() 声明的枚举(须限定为 enum 包的 InitFor,同名其他函数不误报)
  • 检测以下写入:
    • X = ... — 整体重写枚举变量
    • X.Field = ... / X.Field += ... — 字段赋值、复合赋值
    • X.Field++ / X.Field-- — 自增自减
    • 跨包写入 pkg.X.Field = ...pkg.X = ...(重写另一包枚举变量)同样检测
  • X := ...(短声明)视为局部声明,不误报;函数内局部 shadow 只在自身函数内生效,不影响其他函数对包级枚举的检测
  • 支持自定义 import 别名(import myenum "…/enum"
已知限制
  • 只检测包级枚举;函数内局部 enum.InitFor 不追踪 -- 函数内作用范围小,可自行检查
  • 不校验枚举定义的正确性(重复 value、非法 tag、缺嵌入 Struct[T] 等仍要到运行时 panic)
  • 通过指针间接修改(f(&Events.Field))无法静态检测
  • _test.go 同样受约束(测试代码也不应改写枚举)

设计原则

  • 零外部依赖 — 仅使用 Go 标准库
  • enum tag 格式:"value,name[,disabled]" — 第三段 "disabled" 标记为仅展示不可选
  • 没有 init() — 枚举显式构造,无隐式副作用

ts

type Priority int

type Priorities struct {
    enum.Struct[Priority]
    Low    Priority `enum:"0,低"`
    Medium Priority `enum:"1,中"`
    High   Priority `enum:"2,高,disabled"`
}

用 enum.InitFor 后,Enum.MarshalJSON 的数组元素是:

{"key":"Low","name":"低","value":0}
{"key":"Medium","name":"中","value":1}
{"key":"High","name":"高","disabled":true,"value":2}
  1. 对应的 TS as const 枚举数据
export const PRIORITIES = {
  Low: {
    key: 'Low' as const,
    name: '低' as const,
    value: 0 as const,
  },
  Medium: {
    key: 'Medium' as const,
    name: '中' as const,
    value: 1 as const,
  },
  High: {
    key: 'High' as const,
    name: '高' as const,
    value: 2 as const,
    disabled: true as const,
  },
} as const;

这就是「ts {...} as const」部分:每一项有 key / name / value / disabled?,和 Go 侧 JSON 结构一一对应。

  1. 从 as const 中取出 key / value 相关类型
// 所有枚举项的联合类型
export type PriorityItem = (typeof PRIORITIES)[keyof typeof PRIORITIES];

// key 的字面量联合:"Low" | "Medium" | "High"
export type PriorityKey = PriorityItem['key'];

// value 的字面量联合:0 | 1 | 2
export type PriorityValue = PriorityItem['value'];

如果你只想要一个「key 到 value」的简单映射结构,可以再包一层:

// key -> value 的映射对象类型
export type PriorityKeyValueMap = {
  [K in PriorityKey]: Extract<PriorityItem, { key: K }>['value'];
};

// 实例:由 PRIORITIES 推导出的 key/value map
export const PRIORITY_KEY_VALUE: PriorityKeyValueMap = {
  Low: PRIORITIES.Low.value,
  Medium: PRIORITIES.Medium.value,
  High: PRIORITIES.High.value,
};

这样你就同时有:

  • PRIORITIES:完整的枚举元数据(key/name/value/disabled)——对应 Go 侧 Enum.MarshalJSON 的数组元素结构;
  • PriorityKey / PriorityValue:类型级别的 key/value 联合;
  • PRIORITY_KEY_VALUE:在 TS 里方便用的「key → value」映射。

Documentation

Index

Examples

Constants

View Source
const (
	NameKey     = "name"
	ValueKey    = "value"
	DisabledKey = "disabled"
	ExtKey      = "ext"
)

JSON field names shared between jsonItem struct tags and ToMap output.

View Source
const ParentExtKey = "parent"

ParentExtKey is the ext key used by BuildTree to establish parent-child relationships. Items with ext[ParentExtKey] == "…" are treated as children of the item with the matching value.

Variables

This section is empty.

Functions

func InitFor

func InitFor[T EnumBase, R any]() R

InitFor is a one-liner: allocates, inits, and returns a value of R. It delegates to Init so struct validation stays in one place.

p := enum.InitFor[Priority, Priorities]()

Types

type CascaderOption added in v0.2.0

type CascaderOption struct {
	Label    string           `json:"label"`
	Value    string           `json:"value"`
	Disabled bool             `json:"disabled,omitempty"`
	Children []CascaderOption `json:"children,omitempty"`
}

CascaderOption is the Ant Design <Cascader> / <TreeSelect> format, using label instead of name. Produced by Struct[T].TreeOptions().

type Enum

type Enum[T EnumBase] struct {
	// contains filtered or unexported fields
}

Enum is an ordered set of named values. It is logically immutable — items, names, and values are fixed after construction. The only exception is AddExt, which mutates the extension metadata of an existing item; all other fields remain stable.

It is safe for concurrent use after construction, provided AddExt calls are not concurrent with reads.

Example (RoundTrip)
// Create, marshal, unmarshal back — end-to-end.
e := enum.InitFor[OrderStatus, OrderStatuses]()
e.AddExt("Processing", "color", "blue")

// Marshal.
b, _ := json.Marshal(e.Enum())

// Unmarshal into a fresh Enum.
var restored enum.Enum[OrderStatus]
json.Unmarshal(b, &restored)

// Verify.
item, _ := restored.ByKey("Processing")
fmt.Println(item.Name(), item.Ext()["color"])
Output:
处理中 blue

func New

func New[T EnumBase](items ...Item[T]) *Enum[T]

New creates an Enum from the given items. Panics if no items are provided, or if any name or value is duplicated.

func (*Enum[T]) AddExt

func (e *Enum[T]) AddExt(itemKey, extKey, extValue string)

AddExt adds a key-value pair to the named item's extension metadata. No-op when the item is not found. The item's ext map is created on first use. Updates both the items slice and the lookup maps so subsequent ByKey/ByValue calls reflect the change. Panics if the item does not exist — a typo'd key would otherwise be silently ignored, hiding a bug from the caller.

func (*Enum[T]) All

func (e *Enum[T]) All() []Item[T]

All returns a copy of all items in definition order.

func (*Enum[T]) ByKey

func (e *Enum[T]) ByKey(key string) (Item[T], bool)

ByKey returns the item with the given key. The second return value is false when the key does not exist.

func (*Enum[T]) ByValue

func (e *Enum[T]) ByValue(value T) (Item[T], bool)

ByValue returns the item with the given value. The second return value is false when the value does not exist.

func (*Enum[T]) Contains

func (e *Enum[T]) Contains(value T) bool

Contains reports whether the given value is a member of the enum.

func (*Enum[T]) GetExt

func (e *Enum[T]) GetExt(itemKey string) map[string]string

GetExt returns a copy of the named item's extension metadata, or nil when the item is not found.

func (*Enum[T]) Index

func (e *Enum[T]) Index(i int) (Item[T], bool)

Index returns the item at the given position in definition order. The second return value is false when i is out of range.

func (*Enum[T]) Keys

func (e *Enum[T]) Keys() []string

Keys returns all programmatic keys in definition order.

func (*Enum[T]) Len

func (e *Enum[T]) Len() int

Len returns the number of items.

func (*Enum[T]) MarshalJSON

func (e *Enum[T]) MarshalJSON() ([]byte, error)

MarshalJSON serializes the enum as an ordered array of {key, name, value, disabled?, ext?}.

Example (Int)
statuses := enum.InitFor[OrderStatus, OrderStatuses]()
b, _ := json.Marshal(statuses.Enum())
fmt.Println(string(b))
Output:
[{"key":"Pending","name":"待处理","value":0},{"key":"Processing","name":"处理中","value":1},{"key":"Shipped","name":"已发货","value":2},{"key":"Cancelled","name":"已取消","value":3,"disabled":true}]
Example (String)
e := enum.InitFor[Severity, SeverityEnum]()
b, _ := json.Marshal(e.Enum())
fmt.Println(string(b))
Output:
[{"key":"Info","name":"信息","value":"INFO"},{"key":"Warn","name":"警告","value":"WARN"},{"key":"Error","name":"错误","value":"ERROR"}]

func (*Enum[T]) MustByKey

func (e *Enum[T]) MustByKey(key string) Item[T]

MustByKey returns the item with the given key, panicking if it doesn't exist.

func (*Enum[T]) MustByValue

func (e *Enum[T]) MustByValue(value T) Item[T]

MustByValue returns the item with the given value, panicking if it doesn't exist.

func (*Enum[T]) MustIndex

func (e *Enum[T]) MustIndex(i int) Item[T]

MustIndex returns the item at position i, panicking if out of range.

func (*Enum[T]) Range

func (e *Enum[T]) Range() iter.Seq2[string, Item[T]]

Range iterates over all items in definition order, yielding (key, item).

func (*Enum[T]) ToMap

func (e *Enum[T]) ToMap() map[string]map[string]any

ToMap returns each item keyed by its key. Useful when the frontend needs O(1) lookup by key instead of array iteration:

json.NewEncoder(w).Encode(event.Events.ToMap())
// → {UserCreated: {name:"用户创建", value:"user.created"}, ...}
Example

ToMap as JSON.

e := enum.InitFor[Severity, SeverityEnum]()
b, _ := json.Marshal(e.ToMap())
fmt.Println(string(b))
Output:
{"Error":{"name":"错误","value":"ERROR"},"Info":{"name":"信息","value":"INFO"},"Warn":{"name":"警告","value":"WARN"}}

func (*Enum[T]) UnmarshalJSON

func (e *Enum[T]) UnmarshalJSON(data []byte) error

UnmarshalJSON reconstructs the enum from a JSON array. Returns an error on duplicate names/values or invalid JSON.

Example
data := []byte(`[{"key":"Low","name":"低","value":0},{"key":"High","name":"高","value":2}]`)
var e enum.Enum[Priority]
if err := json.Unmarshal(data, &e); err != nil {
	panic(err)
}
item, _ := e.ByKey("High")
fmt.Println("found:", item.Name(), "→", item.Value())
Output:
found: 高 → 2

func (*Enum[T]) Values

func (e *Enum[T]) Values() []T

Values returns all values in definition order.

type EnumBase

type EnumBase interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 |
		~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
		~string
}

EnumBase is the type constraint for enum value types. Only int/uint/string-based types are supported.

type Item

type Item[T EnumBase] struct {
	// contains filtered or unexported fields
}

Item is one member of an enum—a programmatic key, a human-readable name, and a value. Fields are private; use the accessor methods to read them.

func AsStringItems

func AsStringItems[T EnumBase](items []Item[T]) []Item[string]

AsStringItems converts a typed Item slice to []Item[string] using fmt.Sprint for the value. This allows combining items from different enum types into a single BuildTree input.

func ItemFrom

func ItemFrom[T EnumBase](key, name string, value T, opts ...ItemOption[T]) Item[T]

ItemFrom creates an Item. key is the programmatic identifier (e.g. "Monday"); name is the human-readable label (e.g. "周一"). Options like WithDisabled and WithExt are applied last.

func (Item[T]) Ext

func (i Item[T]) Ext() map[string]string

func (Item[T]) IsDisabled

func (i Item[T]) IsDisabled() bool

func (Item[T]) Key

func (i Item[T]) Key() string

func (Item[T]) Name

func (i Item[T]) Name() string

func (Item[T]) Value

func (i Item[T]) Value() T

type ItemOption

type ItemOption[T EnumBase] func(*Item[T])

ItemOption is a functional option for ItemFrom.

func WithDisabled

func WithDisabled[T EnumBase]() ItemOption[T]

WithDisabled marks the item as disabled (display-only, not selectable).

func WithExt

func WithExt[T EnumBase](m map[string]string) ItemOption[T]

WithExt sets extension metadata on the item.

type Struct

type Struct[T EnumBase] struct {
	// contains filtered or unexported fields
}

Struct is a reflection-driven enum backed by Enum[T]. Use InitFor:

type Statuses struct {
    Struct[Status]  // embed anywhere (found by scanning anonymous fields)
    Pending Status  `enum:"0,待处理"`
    Active  Status  `enum:"1,活跃"`
}

s := enum.InitFor[Status, Statuses]()
s.ByKey("Active")     // → Item, true
switch v { case s.Pending: ... }
Example (Embedded_marshal)
e := enum.InitFor[Severity, SeverityEnum]()
b, _ := json.Marshal(e.Enum())
var items []map[string]any
json.Unmarshal(b, &items)
fmt.Println(items[0]["key"], items[0]["name"])
Output:
Info 信息
Example (Embedded_unmarshal)
// Unmarshal replaces the underlying enum data.
data := []byte(`[{"key":"A","name":"甲","value":1}]`)
var e enum.Enum[Priority]
json.Unmarshal(data, &e)
fmt.Println(e.Len(), e.Contains(Priority(1)))
Output:
1 true

func (*Struct[T]) AddExt

func (s *Struct[T]) AddExt(itemKey, extKey, extValue string)

func (*Struct[T]) All

func (s *Struct[T]) All() []Item[T]

func (*Struct[T]) ByKey

func (s *Struct[T]) ByKey(name string) (Item[T], bool)

func (*Struct[T]) ByValue

func (s *Struct[T]) ByValue(value T) (Item[T], bool)

func (*Struct[T]) Contains

func (s *Struct[T]) Contains(value T) bool

func (*Struct[T]) Enum

func (s *Struct[T]) Enum() *Enum[T]

Enum returns the underlying Enum[T]. When Struct is embedded in another struct that has its own exported fields, Go's JSON encoder ignores the embedded MarshalJSON/UnmarshalJSON — use .Enum() to serialize/deserialize directly:

json.NewEncoder(w).Encode(event.Events.Enum())       // marshal
json.NewDecoder(r).Decode(event.Events.Enum())       // unmarshal

Returns nil when the Struct has not been initialized via InitFor.

func (*Struct[T]) GetExt

func (s *Struct[T]) GetExt(itemKey string) map[string]string

func (*Struct[T]) Index

func (s *Struct[T]) Index(i int) (Item[T], bool)

func (*Struct[T]) Keys

func (s *Struct[T]) Keys() []string

func (*Struct[T]) Len

func (s *Struct[T]) Len() int

func (*Struct[T]) MarshalJSON

func (s *Struct[T]) MarshalJSON() ([]byte, error)

MarshalJSON / UnmarshalJSON delegate to the underlying enum. They return an error (rather than panic) when the Struct is uninitialized.

Example
p := enum.InitFor[Priority, Priorities]()
b, _ := json.Marshal(p)
fmt.Println(string(b))
Output:
{"Low":0,"Medium":1,"High":2}
Example (Struct)
p := enum.InitFor[Priority, Priorities]()
sb, _ := json.Marshal(p.Struct)
fmt.Println(string(sb))
Output:
{}

func (*Struct[T]) MustByKey

func (s *Struct[T]) MustByKey(name string) Item[T]

func (*Struct[T]) MustByValue

func (s *Struct[T]) MustByValue(value T) Item[T]

func (*Struct[T]) MustIndex

func (s *Struct[T]) MustIndex(i int) Item[T]

func (*Struct[T]) Range

func (s *Struct[T]) Range() iter.Seq2[string, Item[T]]

func (*Struct[T]) ToMap

func (s *Struct[T]) ToMap() map[string]map[string]any

func (*Struct[T]) Tree added in v0.2.0

func (s *Struct[T]) Tree() []TreeNode

Tree returns the enum items as a recursive TreeNode tree.

func (*Struct[T]) TreeOptions added in v0.2.0

func (s *Struct[T]) TreeOptions() []CascaderOption

TreeOptions converts the tree to Ant Design Cascader format.

func (*Struct[T]) UnmarshalJSON

func (s *Struct[T]) UnmarshalJSON(data []byte) error

func (*Struct[T]) Values

func (s *Struct[T]) Values() []T

type TreeNode

type TreeNode struct {
	Key      string     `json:"key"`
	Name     string     `json:"name"`
	Value    string     `json:"value"`
	Disabled bool       `json:"disabled,omitempty"`
	Children []TreeNode `json:"children,omitempty"`
}

TreeNode is a recursive frontend node for multi-level dropdowns.

func BuildTree

func BuildTree[T EnumBase](items []Item[T]) []TreeNode

BuildTree converts a flat item list into a recursive tree keyed by ext["parent"]. Items without a parent (or whose parent doesn't match any item) become roots.

Example

BuildTree produces nested JSON for multi-level dropdowns.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/donnol/enum"
)

func main() {
	items := []enum.Item[string]{
		enum.ItemFrom("Fruit", "水果", "FRUIT"),
		enum.ItemFrom("Vegetable", "蔬菜", "VEGETABLE"),
		enum.ItemFrom("Apple", "苹果", "APPLE",
			enum.WithExt[string](map[string]string{enum.ParentExtKey: "FRUIT"})),
		enum.ItemFrom("Banana", "香蕉", "BANANA",
			enum.WithExt[string](map[string]string{enum.ParentExtKey: "FRUIT"}),
			enum.WithDisabled[string]()),
		enum.ItemFrom("Carrot", "胡萝卜", "CARROT",
			enum.WithExt[string](map[string]string{enum.ParentExtKey: "VEGETABLE"})),
	}

	tree := enum.BuildTree(items)
	b, _ := json.MarshalIndent(tree, "", "  ")
	fmt.Println(string(b))

}
Output:
[
  {
    "key": "Fruit",
    "name": "水果",
    "value": "FRUIT",
    "children": [
      {
        "key": "Apple",
        "name": "苹果",
        "value": "APPLE"
      },
      {
        "key": "Banana",
        "name": "香蕉",
        "value": "BANANA",
        "disabled": true
      }
    ]
  },
  {
    "key": "Vegetable",
    "name": "蔬菜",
    "value": "VEGETABLE",
    "children": [
      {
        "key": "Carrot",
        "name": "胡萝卜",
        "value": "CARROT"
      }
    ]
  }
]

Directories

Path Synopsis
cmd
enumlint command
Command enumlint is the CLI for the enumlint package.
Command enumlint is the CLI for the enumlint package.
Package enumlint checks that enum values (created with enum.InitFor) are never written to after initialization.
Package enumlint checks that enum values (created with enum.InitFor) are never written to after initialization.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL