英文:
Extending constants in Golang
问题
这是我的要求:我有两组常量。我想形成第三组常量,即上述两组常量的并集。我该如何实现?
type CompOp byte
const (
EQUAL CompOp = iota
NOT_EQUAL
)
type LogOp byte
const (
AND LogOp = iota
OR
)
我想要一个第三组常量,比如说Operator:
type Op struct {
CompOp
LogOp
}
或者
var Op = CompOp + LogOp
但是上述两种方式都不起作用。我该如何实现这个要求?
对我来说,上述内容很重要,我正在尝试实现以下内容:
type logExpr struct {
expr Expression
op LogOp
}
type compExpr struct {
expr Expression
op CompOp
}
type filterExpr struct {
expr Expression
op Op
}
英文:
Here's my requirement: I have 2 sets of constants. I want to form a third set which is nothing but a union of the above 2 sets. How do I achieve that?
type CompOp byte
const (
EQUAL CompOp = iota
NOT_EQUAL
)
type LogOp byte
const (
AND LogOp = iota
OR
)
I want a third set, say Operator
type Op {CompOp, LogOp}
or
var Op = CompOp + LogOp
But neither of the above 2 ways work. How do I achieve this requirement?
The above is important to me I'm trying to achieve this :
type logExpr struct {
expr Expression
op LogOp
}
type compExpr struct {
expr Expression
op CompOp
}
type filterExpr struct {
expr Expression
op Op
}
答案1
得分: 6
CompOp
和LogOp
不是相同类型的集合。它们不能以这种方式组合在一起。即使可以,它们也会发生冲突,因为EQUAL
和AND
都是0(因为它们是它们所在块中的第一个iota
)。你需要另一种设计。
最常见的设计是将所有运算符组合到一个单独的const
块中,然后提供像IsCompare()
或IsLogic()
这样的函数来区分它们(如果有必要的话)。可以参考os.IsExist()
和os.IsPermission()
作为模板。
以下是我可能实现的一种方式。它浪费了一些值用于min/max,但代码非常简单易读且易于更新。
const (
// Comparison operators
minComparison Op = iota
EQUAL
NOT_EQUAL
maxComparison
// Logic operators
minLogic
AND
OR
maxLogic
)
func IsComparsion(op Op) bool {
return op >= minComparison && op <= maxComparison
}
func IsLogic(op Op) bool {
return op >= minLogic && op <= maxLogic
}
但是,你可以将不同类型的操作符视为类型吗?是的,你可以,而且也许对你来说效果更好。例如,考虑以下代码:
type Op interface {
isOp()
}
type CompOp byte
const (
EQUAL CompOp = iota
NOT_EQUAL
)
func (op CompOp) isOp() {}
type LogOp byte
const (
AND LogOp = iota
OR
)
func (op LogOp) isOp() {}
func doOpThingBasedOnValue(op Op) {
switch op {
case EQUAL:
println("passed equal")
case AND:
println("passed and")
}
}
func doOpThingBasedOnType(op Op) {
switch op.(type) {
case CompOp:
println("passed a comp")
case LogOp:
println("passed a logic")
}
}
也许这更接近你所考虑的。请注意,即使AND
和EQUAL
都是“0”,作为接口,它们是可区分的,因此我们可以像你期望的那样在它们上进行切换。Go 在这方面很酷。
英文:
CompOp
and LogOp
are not sets of the same type. They cannot be combined this way. If they could, they would conflict anyway, since both EQUAL
and AND
are both 0 (since they're the first iota
in their blocks). You will need another design.
The most common design would be to combine all the operators into a single const
block, and then provide functions like IsCompare()
or IsLogic()
to distinguish them if that's necessary. See os.IsExist()
and os.IsPermission()
as a template.
Here's one way that I might implement it. It wastes a few values for min/max, but it keeps the code very simple to read and easy to update.
const (
// Comparison operators
minComparison Op = iota
EQUAL
NOT_EQUAL
maxComparison
// Logic operators
minLogic
AND
OR
maxLogic
)
func IsComparsion(op Op) bool {
return op >= minComparison && op <= maxComparison
}
func IsLogic(op Op) bool {
return op >= minLogic && op <= maxLogic
}
But can you treat the different kinds of ops as types? Yeah, you can, and maybe it'll work better for you. For example, consider (playground):
type Op interface {
isOp()
}
type CompOp byte
const (
EQUAL CompOp = iota
NOT_EQUAL
)
func (op CompOp) isOp() {}
type LogOp byte
const (
AND LogOp = iota
OR
)
func (op LogOp) isOp() {}
func doOpThingBasedOnValue(op Op) {
switch op {
case EQUAL:
println("passed equal")
case AND:
println("passed and")
}
}
func doOpThingBasedOnType(op Op) {
switch op.(type) {
case CompOp:
println("passed a comp")
case LogOp:
println("passed a logic")
}
}
So maybe that's even closer to what you're thinking of. Note that even though both AND
and EQUAL
are "0", as an interface, they are distinguishable, so we can switch on them like you'd want. Go is cool that way.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论