英文:
ENUMs for custom types in GO
问题
我正在尝试为我定义的类型生成一个枚举。
type FeeStage int
从这里我了解到可以使用iota
基于这个类型创建一个枚举。
const (
Stage1 FeeStage = iota
Stage2
Stage3
)
然而,操作枚举的实际值相当麻烦且容易出错。
const (
Stage1 FeeStage = iota // 0
Stage2 = iota + 6 // 7
Stage3 = (iota - 3) * 5 // -5
)
是否有一种方法可以自动将具有自定义值的ENUM列表转换为特定类型?之前我使用的方法只能将常量的第一个成员转换为自定义类型。
const (
Stage1 FeeStage = 1
Stage2 = 2
Stage3 = 2
)
这里是一个类似结果的示例。
英文:
I am trying to generate an enum for a type I defined
type FeeStage int
From this I learned that I can use iota to create an enum based on this type
const(
Stage1 FeeStage = iota
Stage2
Stage3
)
However, manipulating the actual values of the enum is rather cumbersome and error prone
const(
Stage1 FeeStage = iota // 0
Stage2 = iota + 6 // 7
Stage3 = (iota - 3) * 5 // -5
)
Is there a way to automatically convert a list of ENUMs with custom values to a certain type. This is what I was using before but only converts the first member of the constant to the custom type.
const(
Stage1 FeeStage = 1
Stage2 = 2
Stage3 = 2
)
Here is a playground with a similar result
答案1
得分: 8
没有其他方法,除非使用iota
和自动枚举,或者做最直接的事情:
const (
Stage1 FeeStage = 1
Stage2 FeeStage = 2
// 或者使用相同结果的另一种语法
Stage3 = FeeStage(2)
)
在我看来,这比像iota + 5
这样的操作要简单。
如果值在程序的上下文之外不重要,我通常使用iota
,如果需要将值用于协议或其他用途,则使用显式类型。
不过我必须说,有时候只使用整数或字符串就足够了,这取决于上下文。例如,可以查看标准库中的HTTP状态码,它们没有特殊的类型。
英文:
There's no way beyond either using iota
and automatic enums, or doing the most straightforward thing:
const(
Stage1 FeeStage = 1
Stage2 FeeStage = 2
// or another syntax with same results
Stage3 = FeeStage(2)
)
which IMHO is less cumbersome than doing stuff like iota + 5
which as you said is really bad.
I usually either use iota if the value is not important beyond the context of the program, or explicit typing if I need the values to be used in a protocol or something.
Though I have to say sometimes just using ints or strings is good enough, it depends on the context. See for example the http status codes in the standard library. They don't have a special type.
答案2
得分: 2
你可能需要澄清一下你实际想要对枚举常量做什么,但看起来你正在尝试为自定义类型分配任意值。
如果你将常量和初始化结构化并按照一定的模式进行排序,使用iota
并不需要很麻烦。Effective Go也有相关的章节。
你可以为枚举常量创建相当复杂的模式,这样就不会出错且不会很麻烦。
英文:
You should maybe clarify what you're actually wanting to do with enumerated constants, but it looks like you're trying to assign arbitrary values to your custom type.
Using iota
doesn't need to be cumbersome if you structure your constants and the initialization to be ordered and to follow a pattern. Effective Go has a section on this too.
You can create fairly complicated patterns for enumerated constants, which doesn't have to be error-prone and cumbersome.
答案3
得分: 1
实际上有一种方法。但是让我们先澄清一些事情。
在常量声明中,如果指定了类型,常量将采用指定的类型:
const n int64 = 3 // n将是一个有类型的常量,其类型为int64
如果省略了类型,常量将采用表达式的类型:
const x = int16(3) // x将是一个有类型的常量,其类型为int16
如果表达式是无类型常量,声明的常量将保持为无类型常量:
const i = 1 // i将是一个无类型整数常量
请注意,如果您尝试打印i
的类型(例如使用fmt.Printf("%T", i)
),您将看到int
,这是因为当将常量传递给函数或将其赋值给变量时,它必须转换为实际的类型,并且将使用默认类型(因为fmt.Println()
的参数类型为interface{}
)-对于无类型整数常量,默认类型为int
。
在括号中的const
声明列表中,可以省略声明中的表达式列表(除了第一个)。如果省略了表达式,将使用先前的非空表达式(文本替换)。
所以当您这样做时:
const(
Stage1 FeeStage = iota
Stage2
Stage3
)
它的意思是:
const (
Stage1 FeeStage = iota
Stage2 FeeStage = iota
Stage3 FeeStage = iota
)
这将产生3个新的常量:Stage1
,Stage2
和Stage3
,它们都是类型为FreeStage
的常量。
您的第二个示例:
const (
Stage1 FeeStage = iota // 0
Stage2 = iota + 6 // 7
Stage3 = (iota - 3) * 5 // -5
)
由于您没有省略表达式,只有第一个常量Stage1
将是一个有类型的常量(类型为FreeStage
),其余的将是无类型常量!所以这甚至不符合您的要求!
现在来谈谈您的问题:您想要这样的东西:
const(
Stage1 FeeStage = 1
Stage2 = 2
Stage3 = 2
)
如上所述,如果省略类型,Stage2
和Stage3
将是无类型常量。因此,必须指定类型,您可以利用常量规范的以下事实:
ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
您可以指定一个标识符_列表_:
const(
Stage1, Stage2, Stage3 FeeStage = 1, 2, 2
)
这样更易读吗?也许如果只有几个常量。如果有很多,请使用Not_a_Golfer的建议:
const(
Stage1 FeeStage = 1
Stage2 FeeStage = 2
Stage3 FeeStage = 2
)
英文:
Actually there's a way. But let's clear some things first.
In constant declarations, if the type is present, the constant will take the specified type:
const n int64 = 3 // n will be a typed constant, its type will be int64
If the type is omitted, the constant will take the type of the expression:
const x = int16(3) // x will be a typed constant, its type will be int16
If the expression is an untyped constant, the declared constant will remain untyped constant:
const i = 1 // i will be an untyped integer constant
Note that if you try to print i
's type (e.g. with fmt.Printf("%T", i)
, you will see int
, and that's because when passing a constant to a function or when assigning it to a variable, it has to be converted to an actual type, and the default type will be used (because fmt.Println()
has arguments type of interface{}
) - which is int
for an untyped integer constant.
Within a parenthesized const
declaration list the expression list may be omitted from declarations (except at the first). If the expression is missing, the previous non-empty expression will be used (textual substitution).
So when you do this:
const(
Stage1 FeeStage = iota
Stage2
Stage3
)
It means:
const (
Stage1 FeeStage = iota
Stage2 FeeStage = iota
Stage3 FeeStage = iota
)
Which results in 3 new constants: Stage1
, Stage2
and Stage3
, all being of type FreeStage
.
Your second example:
const (
Stage1 FeeStage = iota // 0
Stage2 = iota + 6 // 7
Stage3 = (iota - 3) * 5 // -5
)
Since you didn't omit the expressions, ONLY your first constant Stage1
will be a typed constant (of type FreeStage
), the rest will be untyped constants! So this doesn't even qualify (doesn't comply with your requirements)!
And now to your point: you want something like this:
const(
Stage1 FeeStage = 1
Stage2 = 2
Stage3 = 2
)
As stated above, if you leave out the type, Stage2
and Stage3
will be untyped constants. So type must be specified, you may take advantage of the fact that a const specification is:
ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
You may specify an identifier list:
const(
Stage1, Stage2, Stage3 FeeStage = 1, 2, 2
)
Is this more readable? Maybe if there are a few constants only. If there are many, use Not_a_Golfer's recommendation:
const(
Stage1 FeeStage = 1
Stage2 FeeStage = 2
Stage3 FeeStage = 2
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论