Go Enumerations: Difference between revisions
(11 intermediate revisions by the same user not shown) | |||
Line 9: | Line 9: | ||
=Overview= | =Overview= | ||
Go does not have formal enums, but the language allows for sets of related, yet distinct <code>int</code> constants. They represent a property that has several distinct possible <code>int</code> values, like the days of the weeks or the months of the year. | Go does not have formal enums, but the language allows for sets of related, yet distinct <code>int</code> constants. They represent a property that has several distinct possible <code>int</code> values, like the days of the weeks or the months of the year. To make the enumeration constants visible outside the package, they need to start with a capital letter. | ||
These auto-incrementing <code>int</code> constants are declared using a special syntax involving the <code>const</code> keyword, parentheses, a type and the [[Go_Language#Pre-Declared_Constants|pre-declared constant]] <code>[[Go_iota|iota]]</code>: | These auto-incrementing <code>int</code> constants are declared using a special syntax involving the <code>const</code> keyword, parentheses, a type and the [[Go_Language#Pre-Declared_Constants|pre-declared constant]] <code>[[Go_iota|iota]]</code>: | ||
Line 27: | Line 27: | ||
{{Internal|Go_iota#How_Does_the_Compiler_Assign_Values_to_iota|How Does the Compiler Assign Values to iota}} | {{Internal|Go_iota#How_Does_the_Compiler_Assign_Values_to_iota|How Does the Compiler Assign Values to iota}} | ||
The short story is that <code>iota</code> takes the zero-based index of the constant declaration it is used for, as it appears in the <code>const()</code> list. The first declaration is the explicit one, the subsequent ones are implicit. | |||
Example: | Example: | ||
Line 33: | Line 35: | ||
type DayOfTheWeek int | type DayOfTheWeek int | ||
const ( | const ( | ||
UNDEFINED_DAY DayOfTheWeek = iota // iota is equal with 0, which is the zero value for int | |||
MON | |||
TUE | TUE | ||
WED | WED | ||
Line 43: | Line 46: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Only the first constant in the series declares its type and an expression involving <code>iota</code>. The simplest is <code>iota</code> itself, but more complex expressions can be used. | Only the first constant in the series explicitly declares its type and an expression involving <code>iota</code>. The subsequent declaration assume the same type and expression. | ||
The simplest expression involving <code>iota</code> is <code>iota</code> itself, but more complex expressions can be used. Different declarations for enums part of the same set can use different iota expressions, and for those enum declaration that do not have an explicit declaration, the last one applies. | |||
<syntaxhighlight lang='go'> | <syntaxhighlight lang='go'> | ||
type ByteSize float64 | type ByteSize float64 | ||
const ( | const ( | ||
UNDEFINED ByteSize = iota // assign the first value, which is zero, and the zero value for it, to an 'UNDEFINED' enum element | |||
KB ByteSize = 1 << (10 * iota) // gets 1024 | |||
MB // 1 << (10 * iota) applies, MB gets 1048576 | |||
GB // ... | |||
TB | |||
PB | |||
EB | |||
ZB | |||
YB | |||
) | ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=Default Enum Value= | |||
It is a good practice to declare the first enum element in the series as the default value for the enum set, and explicitly name it as such. | |||
If there is an obvious candidate for the default value, use that name. | |||
Otherwise, use "Undefined", and make sure its value is the zero value for the enum's type. In case of <code>int</code>, the zero-value is 0. | |||
<syntaxhighlight lang='go'> | |||
type SomeType int | |||
const ( | |||
Undefined SomeType = iota // gets 0, as the zero-value for int | |||
ElemOne | |||
ElemTwo | |||
) | |||
</syntaxhighlight> | |||
=Naming Convention= | |||
<font color=darkkhaki>Is it good practice to include the type name in the enum element name?</font> | |||
<syntaxhighlight lang='go'> | |||
type QuotaType int | |||
const ( | |||
UndefinedQuotaType QuotaType = iota | |||
AbsoluteQuotaType | |||
FractionalQuotaType | |||
) | |||
</syntaxhighlight> | |||
=String Representation= | =String Representation= |
Latest revision as of 20:30, 13 September 2024
External
Internal
Overview
Go does not have formal enums, but the language allows for sets of related, yet distinct int
constants. They represent a property that has several distinct possible int
values, like the days of the weeks or the months of the year. To make the enumeration constants visible outside the package, they need to start with a capital letter.
These auto-incrementing int
constants are declared using a special syntax involving the const
keyword, parentheses, a type and the pre-declared constant iota
:
type SomeType int
const (
UndefinedEnum SomeType = iota
EnumOne
EnumTwo
...
)
This article explains how iota
is used to generate values for enumeration members:
The short story is that iota
takes the zero-based index of the constant declaration it is used for, as it appears in the const()
list. The first declaration is the explicit one, the subsequent ones are implicit.
Example:
type DayOfTheWeek int
const (
UNDEFINED_DAY DayOfTheWeek = iota // iota is equal with 0, which is the zero value for int
MON
TUE
WED
THU
FRI
SAT
SUN
)
Only the first constant in the series explicitly declares its type and an expression involving iota
. The subsequent declaration assume the same type and expression.
The simplest expression involving iota
is iota
itself, but more complex expressions can be used. Different declarations for enums part of the same set can use different iota expressions, and for those enum declaration that do not have an explicit declaration, the last one applies.
type ByteSize float64
const (
UNDEFINED ByteSize = iota // assign the first value, which is zero, and the zero value for it, to an 'UNDEFINED' enum element
KB ByteSize = 1 << (10 * iota) // gets 1024
MB // 1 << (10 * iota) applies, MB gets 1048576
GB // ...
TB
PB
EB
ZB
YB
)
Default Enum Value
It is a good practice to declare the first enum element in the series as the default value for the enum set, and explicitly name it as such.
If there is an obvious candidate for the default value, use that name.
Otherwise, use "Undefined", and make sure its value is the zero value for the enum's type. In case of int
, the zero-value is 0.
type SomeType int
const (
Undefined SomeType = iota // gets 0, as the zero-value for int
ElemOne
ElemTwo
)
Naming Convention
Is it good practice to include the type name in the enum element name?
type QuotaType int
const (
UndefinedQuotaType QuotaType = iota
AbsoluteQuotaType
FractionalQuotaType
)
String Representation
const
enums can take advantage go the possibility of attaching a String()
method to any type, including the enum type, to provide a string representation.
type DayOfTheWeek int
const (
MON DayOfTheWeek = iota
TUE
WED
THU
FRI
SAT
SUN
)
var dayOfTheWeekToString = []string{
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
}
func (s DayOfTheWeek) String() string {
return dayOfTheWeekToString[s]
}
func StringToDayOfTheWeek(s string) DayOfTheWeek {
for i, v := range dayOfTheWeekToString {
if s == v {
return DayOfTheWeek(i)
}
}
return DayOfTheWeek(-1)
}