Constants
The value of constants in Go cannot be changed at runtime. Once assigned, it cannot be modified. Its value can only come from:
- Literals
- Other constant identifiers
- Constant expressions
- Type conversions that result in constants
- iota
Constants can only be basic data types and cannot be:
- Other types besides basic types, such as structs, interfaces, slices, arrays, etc.
- Function return values
The value of constants cannot be modified, otherwise it won't compile.
Initialization
Constants are declared using the const keyword. A constant must be initialized with a value when declared, and the type of the constant can be omitted.
const name string = "Jack" // Literal
const msg = "hello world" // Literal
const num = 1 // Literal
const numExpression = (1+2+3) / 2 % 100 + num // Constant expressionIf you only declare without assigning a value, it won't compile:
const name stringThe compiler will report an error:
missing init expr for nameBatch declaration of constants can use () to improve readability. Multiple () can be used to achieve grouping.
const (
Count = 1
Name = "Jack"
)
const (
Size = 16
Len = 25
)In the same constant group, constants after an assigned constant don't need to be assigned. Their value defaults to the previous value:
const (
A = 1
B // 1
C // 1
D // 1
E // 1
)iota
iota is a built-in constant identifier, usually used to represent an untyped integer ordinal in a constant declaration. It is generally used within parentheses.
const iota = 0Let's look at some usage cases:
const (
Num = iota // 0
Num1 // 1
Num2 // 2
Num3 // 3
Num4 // 4
)Can also be written like this:
const (
Num = iota*2 // 0
Num1 // 2
Num2 // 4
Num3 // 6
Num4 // 8
)Or:
const (
Num = iota << 2*3 + 1 // 1
Num1 // 13
Num2 // 25
Num3 = iota // 3
Num4 // 4
)From the examples above, we can see that iota is incremental. The first constant using iota is assigned an expression, and based on the ordinal value changes, it will automatically assign values to subsequent constants until a new const resets it. This ordinal is actually the relative line number of the code, relative to the first line of the current group.
const (
Num = iota<<2*3 + 1 // 1 First line
Num2 = iota<<2*3 + 1 // 13 Second line
_ // 25 Third line
Num3 //37 Fourth line
Num4 = iota // 4 Fifth line
_ // 5 Sixth line
Num5 // 6 Seventh line
)The example uses the anonymous identifier _ to occupy a line. You can see that the value of iota is essentially the difference between the line where iota is located and the first line of the current const group. Different const groups don't affect each other.
Enums
Go doesn't have a separate data type for enums, unlike other languages which usually have an enum. Generally in Go, enums are implemented through custom types + const + iota. Here is a simple example:
type Season uint8
const (
Spring Season = iota
Summer
Autumn
Winter
)These enums are actually numbers. Go also doesn't support direct conversion to strings, but we can add methods to custom types to return their string representation by implementing the Stringer interface.
func (s Season) String() string {
switch s {
case Spring:
return "spring"
case Summer:
return "summer"
case Autumn:
return "autumn"
case Winter:
return "winter"
}
return ""
}This is a simple enum implementation. You can also use the official tool Stringer to automatically generate enums.
However, it has the following disadvantages:
Type unsafe, because
Seasonis a custom type, other numbers can be forcibly converted to this typegoSeason(6)Tedious, string representation needs to be implemented manually
Weak expressiveness, because
constonly supports basic data types, these enum values can only be represented with strings and numbers
Why doesn't Go support enums at the language level is something I really don't understand. I think it would definitely be more beneficial than detrimental.
