From cd43004a9161ec0ce12765f563900966aa3c87ef Mon Sep 17 00:00:00 2001 From: dudaodong Date: Tue, 14 Oct 2025 16:37:02 +0800 Subject: [PATCH] feat: add example for enum package --- enum/enum.go | 41 +++++++ enum/enum_example_test.go | 222 ++++++++++++++++++++++++++++++++++++++ enum/enum_test.go | 55 ++++++++++ 3 files changed, 318 insertions(+) create mode 100644 enum/enum_example_test.go diff --git a/enum/enum.go b/enum/enum.go index 690e7e7..86272da 100644 --- a/enum/enum.go +++ b/enum/enum.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "reflect" + "sort" "sync" ) @@ -15,6 +16,7 @@ import ( type Enum[T comparable] interface { Value() T String() string + Name() string Valid() bool } @@ -67,6 +69,10 @@ func (e *Item[T]) Name() string { return e.name } +func (e *Item[T]) String() string { + return e.name +} + // Valid checks if the enum item is valid. If a custom check function is provided, it will be used to validate the value. func (e *Item[T]) Valid(check ...func(T) bool) bool { if len(check) > 0 { @@ -280,3 +286,38 @@ func (r *Registry[T]) Size() int { return len(r.items) } + +// Range iterates over all enum items in the registry and applies the given function. +func (r *Registry[T]) Range(fn func(*Item[T]) bool) { + r.mu.RLock() + defer r.mu.RUnlock() + + for _, item := range r.items { + if !fn(item) { + break + } + } +} + +// SortedItems returns a slice of all enum items sorted by the given less function. +func (r *Registry[T]) SortedItems(less func(*Item[T], *Item[T]) bool) []*Item[T] { + items := r.Items() + sort.Slice(items, func(i, j int) bool { + return less(items[i], items[j]) + }) + return items +} + +// Filter returns a slice of enum items that satisfy the given predicate function. +func (r *Registry[T]) Filter(predicate func(*Item[T]) bool) []*Item[T] { + r.mu.RLock() + defer r.mu.RUnlock() + + var result []*Item[T] + for _, item := range r.items { + if predicate(item) { + result = append(result, item) + } + } + return result +} diff --git a/enum/enum_example_test.go b/enum/enum_example_test.go new file mode 100644 index 0000000..d0d4cb6 --- /dev/null +++ b/enum/enum_example_test.go @@ -0,0 +1,222 @@ +package enum + +import "fmt" + +func ExampleNewItem() { + items := NewItems[Status]( + Active, "Active", + Inactive, "Inactive", + ) + + fmt.Println(items[0].Name(), items[0].Value()) + fmt.Println(items[1].Name(), items[1].Value()) + + // Output: + // Active 1 + // Inactive 2 +} + +func ExampleItem_Valid() { + item := NewItem(Active, "Active") + fmt.Println(item.Valid()) + + invalidItem := NewItem(Unknown, "") + fmt.Println(invalidItem.Valid()) + + // Output: + // true + // false +} + +func ExampleItem_MarshalJSON() { + item := NewItem(Active, "Active") + data, _ := item.MarshalJSON() + fmt.Println(string(data)) + + var unmarshaledItem Item[Status] + _ = unmarshaledItem.UnmarshalJSON(data) + fmt.Println(unmarshaledItem.Name(), unmarshaledItem.Value()) + + // Output: + // {"name":"Active","value":1} + // Active 1 +} + +func ExampleRegistry_Add() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + + registry.Add(item1, item2) + + if item, found := registry.GetByValue(Active); found { + fmt.Println("Found by value:", item.Name()) + } + + if item, found := registry.GetByName("Inactive"); found { + fmt.Println("Found by name:", item.Value()) + } + + // Output: + // Found by value: Active + // Found by name: 2 +} + +func ExampleRegistry_Remove() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + + registry.Add(item1) + fmt.Println("Size before removal:", registry.Size()) + + removed := registry.Remove(Active) + fmt.Println("Removed:", removed) + fmt.Println("Size after removal:", registry.Size()) + + // Output: + // Size before removal: 1 + // Removed: true + // Size after removal: 0 +} + +func ExampleRegistry_Update() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + + registry.Add(item1) + updated := registry.Update(Active, "Activated") + fmt.Println("Updated:", updated) + + if item, found := registry.GetByValue(Active); found { + fmt.Println("New name:", item.Name()) + } + + // Output: + // Updated: true + // New name: Activated +} + +func ExampleRegistry_Items() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + + registry.Add(item1, item2) + + for _, item := range registry.Items() { + fmt.Println(item.Name(), item.Value()) + } + + // Output: + // Active 1 + // Inactive 2 +} + +func ExampleRegistry_Contains() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + registry.Add(item1) + + fmt.Println("Contains Active:", registry.Contains(Active)) + fmt.Println("Contains Inactive:", registry.Contains(Inactive)) +} + +func ExampleRegistry_Validate() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + fmt.Println("Validate Active:", registry.Validate(Active)) + fmt.Println("Validate Inactive:", registry.Validate(Inactive)) + fmt.Println("Validate Unknown:", registry.Validate(Unknown)) + + // Output: + // Validate Active: + // Validate Inactive: + // Validate Unknown: invalid enum value: 0 +} + +func ExampleRegistry_ValidateAll() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + fmt.Println("ValidateAll Active, Inactive:", registry.ValidateAll(Active, Inactive)) + fmt.Println("ValidateAll Active, Unknown:", registry.ValidateAll(Active, Unknown)) + + // Output: + // ValidateAll Active, Inactive: + // ValidateAll Active, Unknown: invalid enum value: 0 +} + +func ExampleRegistry_Size() { + registry := NewRegistry[Status]() + fmt.Println("Initial size:", registry.Size()) + + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + fmt.Println("Size after adding items:", registry.Size()) + + registry.Remove(Active) + fmt.Println("Size after removing an item:", registry.Size()) + + // Output: + // Initial size: 0 + // Size after adding items: 2 + // Size after removing an item: 1 +} + +func ExampleRegistry_Range() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + registry.Range(func(item *Item[Status]) bool { + fmt.Println(item.Name(), item.Value()) + return true // continue iteration + }) + + // Output: + // Active 1 + // Inactive 2 +} + +func ExampleRegistry_SortedItems() { + registry := NewRegistry[Status]() + item1 := NewItem(Inactive, "Inactive") + item2 := NewItem(Active, "Active") + registry.Add(item1, item2) + + for _, item := range registry.SortedItems(func(i1, i2 *Item[Status]) bool { + return i1.value < i2.value + }) { + fmt.Println(item.Name(), item.Value()) + } + + // Output: + // Active 1 + // Inactive 2 +} + +func ExampleRegistry_Filter() { + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + activeItems := registry.Filter(func(item *Item[Status]) bool { + return item.Value() == Active + }) + + for _, item := range activeItems { + fmt.Println(item.Name(), item.Value()) + } + + // Output: + // Active 1 +} diff --git a/enum/enum_test.go b/enum/enum_test.go index 26cf696..5cdb57d 100644 --- a/enum/enum_test.go +++ b/enum/enum_test.go @@ -161,3 +161,58 @@ func TestRegistry_ValidateAll(t *testing.T) { err = registry.ValidateAll(Active, Unknown) assert.IsNotNil(err) } + +func TestRegistry_Range(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestRegistry_Range") + + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + var values []Status + registry.Range(func(item *Item[Status]) bool { + values = append(values, item.Value()) + return true + }) + + assert.Equal(2, len(values)) + assert.Equal(Active, values[0]) + assert.Equal(Inactive, values[1]) +} + +func TestRegistry_SortedItems(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestRegistry_SortedItems") + + registry := NewRegistry[Status]() + item1 := NewItem(Inactive, "Inactive") + item2 := NewItem(Active, "Active") + registry.Add(item1, item2) + + sortedItems := registry.SortedItems(func(i1, i2 *Item[Status]) bool { + return i1.value < i2.value + }) + + assert.Equal(2, len(sortedItems)) + assert.Equal(Active, sortedItems[0].Value()) + assert.Equal(Inactive, sortedItems[1].Value()) +} + +func TestRegistry_Filter(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestRegistry_Filter") + + registry := NewRegistry[Status]() + item1 := NewItem(Active, "Active") + item2 := NewItem(Inactive, "Inactive") + registry.Add(item1, item2) + + filteredItems := registry.Filter(func(item *Item[Status]) bool { + return item.Value() == Active + }) + + assert.Equal(1, len(filteredItems)) + assert.Equal(Active, filteredItems[0].Value()) +}