当前位置: 首页 > 知识库问答 >
问题:

有限值的类型安全枚举[重复]

郗河
2023-03-14

在Go中如何在有限的值范围内实现类型安全枚举?

例如,假设我想用简单的尺寸和颜色对t恤衫进行建模,这两种t恤衫都有有限的可能值,以确保我无法创建具有不受支持的值的实例。

我可以声明类型大小颜色基于字符串,定义有效值的枚举,以及使用它们的TShirt类型:

type Size string
const (
  Small  Size = "sm"
  Medium      = "md"
  Large       = "lg"
  // ...
)

type Color string
const (
  Red   Color = "r"
  Green       = "g"
  Blue        = "b"
  // ...
)

type TShirt struct {
  Size  Size
  Color Color
}

var mediumBlueShirt = TShirt{Medium, Blue}

但是,我如何确保没有创建尺寸/颜色未定义的T恤?

var doNotWant = TShirt{"OutrageouslyLarge", "ImpossibleColor"}

共有2个答案

田仲卿
2023-03-14

不直接支持有限集合枚举,但是您可以使用类型系统来实现:

// Exported interface 
type Size interface {
   // Unexported method
   isSize()
}

// unexported type
type size struct {
   sz string
}

func (s size) String() string {return s.sz}
// Implement the exported interface
func (size) isSize() {}

var (
  Small Size = size{"small"}
  Large Size = size{"large"}
)

这样,您只能使用预先声明的值。

这通常不值得麻烦。考虑针对已知值集验证此类枚举。

徐晔
2023-03-14

如果使枚举基于整数,则可以创建可用于检查有效性的伪值:

type Size int
const (
    Small Size = iota
    Medium
    Large
    maxSize // Always keep this at the end
)

var sizeToString = map[Size]string{
    Small: "sm",
    Medium: "md",
    Large: "lg",
}

func (s Size) String() string {
    return sizeToString[s]
}

func (s Size) Valid() bool {
    return s > 0 && s < maxSize
}

如果您在const块的末尾保留maxsize,则您的Valid函数将始终工作,即使在添加或删除枚举值之后也是如此。

您可以对第二个枚举类型执行相同的操作,并且您的复合类型还可以定义一个Valid函数,如果两个枚举都有效,该函数将返回true。

当我使用这个模式时,我总是包含一个单元测试,以确保每个枚举值都有一个字符串转换,这样我就不会忘记。您可以通过从0到maxsize创建一个for循环来实现这一点,并检查您是否从未从sizeToString中获得空字符串。

 类似资料:
  • 问题内容: Scala没有enumJava所具有的类型安全的。给定一组相关的常数,Scala中代表这些常数的最佳方法是什么? 问题答案: http://www.scala-lang.org/docu/files/api/scala/Enumeration.html 使用范例

  • 枚举类(“新的枚举”/“强类型的枚举”)主要用来解决传统的C++枚举的三个问题: 传统C++枚举会被隐式转换为int,这在那些不应被转换为int的情况下可能导致错误 传统C++枚举的每一枚举值在其作用域范围内都是可见的,容易导致名称冲突(同名冲突) 不可以指定枚举的底层数据类型,这可能会导致代码不容易理解、兼容性问题以及不可以进行前向声明 枚举类(enum)(“强类型枚举”)是强类型的,并且具有类

  • 问题内容: 基本上,我所做的是为州写一个枚举,我不仅希望能够像州一样访问它们,而且还希望访问它们的缩写以及它们是否是原始殖民地。 这似乎按我预期的那样工作。我可以 对于涉及枚举的特定情况,这是执行此操作的最佳方法,还是设置和格式化此枚举的更好方法?预先感谢所有人! 问题答案: 首先,枚举方法不应大写。它们是与其他方法一样的方法,具有相同的命名约定。 其次,您所做的并不是建立枚举的最佳方法。不要为每

  • 为什么我在浏览java时看不到

  • 问题内容: 假设是,我将如何产生给定序数的枚举值? 问题答案: 足够了。一条线; 足够简单。