goenum

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 15, 2023 License: Apache-2.0 Imports: 4 Imported by: 1

README

Go 通用枚举实现

License

怎么定义枚举?

import "github.com/lvyahui8/goenum"

type State struct {
    goenum.Enum
}

var (
    Created = goenum.NewEnum[State]("Created")
    Running = goenum.NewEnum[State]("Running")
    Success = goenum.NewEnum[State]("Success")
)

实例方法

type EnumDefinition interface {
    // Stringer 支持打印输出
    fmt.Stringer
    // Marshaler 支持枚举序列化
    json.Marshaler
    // Init 枚举初始化。使用方不应该直接调用这个方法。
    Init(args ...any) any
    // Name 枚举名称,同一类型枚举应该唯一
    Name() string
    // Equals 枚举对比
    Equals(other EnumDefinition) bool
    // Type 实际的枚举类型
    Type() string
    // Ordinal 获取枚举序数
    Ordinal() int
    // Compare 枚举比较方法
    Compare(other EnumDefinition) int
}

工具方法

  • ValueOf 根据字符串获取枚举,如果找不到,则返回nil

  • ValueOfIgnoreCase 忽略大小写获取枚举, 涉及到一次反射调用,性能比ValueOf略差

  • Values 返回所有枚举

  • GetEnumMap 获取所有枚举,以name->enum map的形式返回

  • EnumNames 获取一批枚举的名称

  • IsValidEnum 判断是否是合法的枚举

func TestHelpers(t *testing.T) {
    t.Run("ValueOf", func(t *testing.T) {
        require.True(t, Owner.Equals(*goenum.ValueOf[Role]("Owner")))
        require.False(t, Developer.Equals(*goenum.ValueOf[Role]("Owner")))
    })
    t.Run("ValueOfIgnoreCase", func(t *testing.T) {
        require.True(t, Owner.Equals(*goenum.ValueOfIgnoreCase[Role]("oWnEr")))
        require.False(t, Reporter.Equals(*goenum.ValueOfIgnoreCase[Role]("oWnEr")))
    })
    t.Run("Values", func(t *testing.T) {
        require.True(t, reflect.DeepEqual([]Role{Reporter, Developer, Owner}, goenum.Values[Role]()))
    })
    t.Run("GetEnumMap", func(t *testing.T) {
        enumMap := goenum.GetEnumMap[Role]()
        require.True(t, len(enumMap) == 3)
        role, exist := enumMap["Owner"]
        require.True(t, exist)
        require.True(t, role.Equals(Owner))
    })
    t.Run("EnumNames", func(t *testing.T) {
        require.True(t, reflect.DeepEqual([]string{"Owner", "Developer"}, goenum.EnumNames(Owner, Developer)))
    })
    t.Run("IsValidEnum", func(t *testing.T) {
        require.True(t, goenum.IsValidEnum[Role]("Owner"))
        require.False(t, goenum.IsValidEnum[Role]("Test"))
    })
}

进阶:复杂枚举初始化

枚举struct 实现Init方法即可,NewEnum方法中的args参数,会完整透传给Init方法,注意,Init方法需要将receiver返回以确保初始化生效

完整例子请看 gitlab_role_perms

type Module struct {
    goenum.Enum
    perms    []Permission
    basePath string
}

func (m Module) Init(args ...any) any {
    m.perms = args[0].([]Permission)
    m.basePath = args[1].(string)
    return m
}

func (m Module) GetPerms() []Permission {
    return m.perms
}

func (m Module) BasePath() string {
    return m.basePath
}


// 定义模块
var (
    Issues        = goenum.NewEnum[Module]("Issues", []Permission{AddLabels, AddTopic}, "/issues/")
    MergeRequests = goenum.NewEnum[Module]("MergeRequests", []Permission{ViewMergeRequest, ApproveMergeRequest, DeleteMergeRequest}, "/merge/")
)

ValueOf性能测试

不用担心任何性能问题,反射调用基本集中在NewEnum方法中,其他方法尽量避免反射调用。

goos: linux
goarch: arm64
pkg: github.com/lvyahui8/goenum/internal
BenchmarkValueOf/ValueOf-4             1000000000             0.0002492 ns/op           0 B/op           0 allocs/op
BenchmarkValueOf/ValueOf-4             1000000000             0.0002966 ns/op           0 B/op           0 allocs/op
BenchmarkValueOf/ValueOf-4             1000000000             0.0002713 ns/op           0 B/op           0 allocs/op
BenchmarkValueOf/ValueOfIgnoreCase-4             1000000000             0.002228 ns/op           0 B/op           0 allocs/op
BenchmarkValueOf/ValueOfIgnoreCase-4             1000000000             0.002611 ns/op           0 B/op           0 allocs/op
BenchmarkValueOf/ValueOfIgnoreCase-4             1000000000             0.002606 ns/op           0 B/op           0 allocs/op
PASS
ok      github.com/lvyahui8/goenum/internal    0.097s

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnumNames

func EnumNames(enums ...EnumDefinition) (names []string)

EnumNames 获取一批枚举的名称

func GetEnumMap

func GetEnumMap[T EnumDefinition]() map[string]T

GetEnumMap 获取所有枚举,以name->enum map的形式返回

func IsValidEnum

func IsValidEnum[T EnumDefinition](name string) bool

IsValidEnum 判断是否是合法的枚举

func NewEnum

func NewEnum[T EnumDefinition](name string, args ...any) T

NewEnum 新建枚举

func ValueOf

func ValueOf[T EnumDefinition](name string) *T

ValueOf 根据字符串获取枚举,如果找不到,则返回nil

func ValueOfIgnoreCase

func ValueOfIgnoreCase[T EnumDefinition](name string) *T

ValueOfIgnoreCase 忽略大小写获取枚举, 涉及到一次反射调用,性能比ValueOf略差

func Values

func Values[T EnumDefinition]() []T

Values 返回所有可用枚举

Types

type Enum

type Enum struct {
	// contains filtered or unexported fields
}

func (Enum) Compare

func (e Enum) Compare(other EnumDefinition) int

func (Enum) Equals

func (e Enum) Equals(other EnumDefinition) bool

func (Enum) Init

func (e Enum) Init(args ...any) any

func (Enum) MarshalJSON

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

func (Enum) Name

func (e Enum) Name() string

func (Enum) Ordinal

func (e Enum) Ordinal() int

func (Enum) String

func (e Enum) String() string

func (Enum) Type

func (e Enum) Type() string

type EnumDefinition

type EnumDefinition interface {
	// Stringer 支持打印输出
	fmt.Stringer
	// Marshaler 支持枚举序列化
	json.Marshaler
	// Init 枚举初始化。使用方不应该直接调用这个方法。
	Init(args ...any) any
	// Name 枚举名称,同一类型枚举应该唯一
	Name() string
	// Equals 枚举对比
	Equals(other EnumDefinition) bool
	// Type 实际的枚举类型
	Type() string
	// Ordinal 获取枚举序数
	Ordinal() int
	// Compare 枚举比较方法
	Compare(other EnumDefinition) int
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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