Skip to content

Implement String() and IsValid() via array, not map #322

Description

@TeaDove

I love go-enum, but maps for String() method could be slow and memory consuming. Bu we could use an index array instead, similar to the approach used by stringer tool:

Now:

var _ColorMap = map[Color]string{
	ColorRED:   _ColorName[0:3],
	ColorGREEN: _ColorName[3:8],
	ColorBLUE:  _ColorName[8:12],
}

// String implements the Stringer interface.
func (x Color) String() string {
	if str, ok := _ColorMap[x]; ok {
		return str
	}
	return fmt.Sprintf("Color(%d)", x)
}

Proposed

var _ColorIndex = [...]uint8{
	0,
	3,
	8,
	12,
}

// String implements the Stringer interface.
func (x Color) String() string {
	if x < 0 || int(x) >= len(_ColorIndex)-1 {
		return fmt.Sprintf("Color(%d)", x)
	}

	return _ColorName[
		_ColorIndex[x]:
		_ColorIndex[x+1],
	]
}

This avoids a map lookup on every String() call and should also reduce the amount of static memory required by the generated code.

Of course, this optimization only works when enum values form a contiguous integer range. Enums with explicitly assigned sparse values, string-backed enums, or other cases where array indexing is not applicable could keep using the existing implementation.

So the generator could choose between:

contiguous integer enum → index array;
sparse/non-contiguous enum → existing map-based implementation.

I'd be happy to submit a PR implementing this, including tests and benchmarks, if the maintainers are interested in this approach.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions