【问题标题】:Best way to enumerate constants in Go在 Go 中枚举常量的最佳方法
【发布时间】:2017-02-02 19:58:27
【问题描述】:

我开始学习其他语言之后的 Go。 Go 有一个非常 elegant way of creating constants 的数值,例如:

const (
    _      = iota    // 0 and is skipped
    Sunday           // 1
    Monday           // 2
    ...
)

这很容易写,但真的容易维护吗?例如,如果您突然在当前之间插入新值,则所有后续都将更改它们的值。而且很难找到,只有仔细阅读差异才能揭示它。或者其他部分的错误。如何使用名称提取这些值并在程序的其他部分或数据库中使用? 例如对于 PostgreSQL,我可以定义:

CREATE TYPE color AS ENUM ('', 'Sunday', 'Monday');

只是为了说明一个想法。例如Python has Enum 输入:

from enum import Enum
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

那么你可以像Color.RED一样使用它。接下来我可以取所有值:

list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

这让我可以“自省”到模块并在数据库中创建易于阅读的枚举。例如对于 PostgreSQL,我可以定义:

CREATE TYPE color AS ENUM ('RED', 'GREEN', 'BLUE');

我该怎么做:

  1. 反映 golang 常量名称?
  2. 制作不会漂移其值的防错常量?只能手动修复吗?
  3. 可能有更好的惯用方法吗?

谢谢。

【问题讨论】:

  • 该值是否改变应该无关紧要,因为您应该按名称使用常量。这是像这样声明常量而不是使用文字值的主要原因。
  • 是的,虽然所有值都在一个程序中,但它们并不重要。但我想在其他人中使用它们,所以我必须翻译一些数值。一旦我使用了它们,我就无法更改它们。或者尽量避免完全数字并只坚持字符串?谢谢

标签: python postgresql go enums idioms


【解决方案1】:

1) 您可以使用 stringer 生成名称https://godoc.org/golang.org/x/tools/cmd/stringer

2) 不确定您的意思?大多数语言都允许您漂移值,如果您希望数字保持不变,则应始终添加到列表的末尾,或者像在 python 中一样,您可以将每个值显式设置为数字而不是使用 iota。

3) 不是真的,枚举在 golang 中并不是很好

【讨论】:

  • 谢谢。 2) 我的意思是,如果新开发人员突然插入的值不在末尾,我的意思是某种方式不允许常量改变它们的值。
  • 是的,要么确保他们将它们添加到列表的末尾,要么明确地将它们设置为一个值而不是使用 iota
【解决方案2】:

只是一个建议,但可能对您的情况有所帮助:我发现如果很明显这些值看起来像位掩码,那么常量以后不太可能被更改/破坏,您可以这样做:

const (
    Red   = 1 << iota
    Green
    Blue
) // values = 1, 2, 4

而且,即使它不是最漂亮的声明,您也可以包含掩码常量

const (
    Red, RedMask = 1 << iota, 1<< iota - 1 // Red = 1, RedMask = 0
    Green, GreenMask                       // Green = 2, mask = 1
    Blue, BlueMask                         // 4, 3
    RGB, RGBMask                           // 8, 7
)

这与为这些常量指定的 type 相结合可能很有用:

type ColourConst int
const (
    Red, RMask ColourConst = 1 << iota, 1 << iota-1
    // ...
    _, All
)

// something like this (untested, might not be correct)
func (c ColourConst) validate() error {
    mask := int(c) & (-1 * int(c))
    if mask != int(c) {
        return errors.New("Colour is not a single bit value")
    }
    if s := c & All; s != c {
        return errors.New("Colour is not in range")
    }
}

我知道一周中的日子不太可能用作位掩码,但它降低了人们破解代码的可能性。至少,它表明常量的顺序很重要,这就是 iota IMO 所做的。

【讨论】:

    【解决方案3】:

    解决方案。 有优秀的模块Enumer 和 Enumelinter

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-21
      • 2016-05-19
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 2011-04-28
      • 1970-01-01
      相关资源
      最近更新 更多