在Golang中扩展常量

huangapple go评论80阅读模式
英文:

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

CompOpLogOp不是相同类型的集合。它们不能以这种方式组合在一起。即使可以,它们也会发生冲突,因为EQUALAND都是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")
    }
}

也许这更接近你所考虑的。请注意,即使ANDEQUAL都是“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.

Playground

const (
	// Comparison operators
	minComparison Op = iota
	EQUAL
	NOT_EQUAL
	maxComparison

	// Logic operators
	minLogic
	AND
	OR
	maxLogic
)

func IsComparsion(op Op) bool {
	return op &gt;= minComparison &amp;&amp; op &lt;= maxComparison
}

func IsLogic(op Op) bool {
	return op &gt;= minLogic &amp;&amp; op &lt;= 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(&quot;passed equal&quot;)
	case AND:
		println(&quot;passed and&quot;)
	}
}

func doOpThingBasedOnType(op Op) {
	switch op.(type) {
	case CompOp:
		println(&quot;passed a comp&quot;)
	case LogOp:
		println(&quot;passed a logic&quot;)
	}
}

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.

huangapple
  • 本文由 发表于 2015年8月17日 20:22:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/32050310.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定