Go

时间:2015-12-29 00:11:44

标签: go

我有一个Go应用程序需要无限数量的常量。该应用程序还要求我能够在运行时将字符串映射到(整数)consts,反之亦然。保证常量的名称只是有效的标识符,因此几乎可以肯定会有重复的const名称。特别是,每组常量都有一个名为"无效"的元素。在C ++ 11中,我使用枚举类来实现范围。在Python中,我可能使用类变量。我努力寻找一种惯用的方式在Go中表达这一点。我查看过的选项包括:

  • 为每组consts使用单独的包。这有很多缺点,因为我宁愿将整个集合放在同一个包中,这样我就可以在包级别上构建对这些集合的支持,这样我就可以测试整个集合而不会过度复杂化测试代码一次进行多包测试。

first.go

package first
type First int
const (
    ConstOne First = iota
    ConstTwo
    Invalid = -1
)

func IntToCode(fi First)string { ... }
func CodeToInt(code string)First { ... }

second.go

package second
type Second int
const (
    ConstOne Second = iota
    ConstTwo
    Invalid = -1
)

func IntToCode(se Second)string { ... }
func CodeToInt(code string)Second { ... }

example.go

import (
    "first"
    "second"
)

First fi = first.CodeToInt("ConstOne")
Second se = second.Invalid
  • 为每个const使用全局唯一前缀的经过验证的技术。但是,考虑到集合的数量非常大,必须使用编码约定来创建和管理一堆命名空间,这种情况最多是尴尬的。此选项还强制我修改consts的名称(这是使用它们的全部要点)。

first.go

package mypackage

type First int

const (
    FI_CONSTONE First = iota
    FI_CONSTTWO
    FI_INVALID = -1
)

func IntToCode(fi First)string { ... }
func CodeToInt(code string)First { ... }

second.go

package mypackage

type Second int

const (
    SE_CONSTONE Second = iota
    SE_CONSTTWO
    SE_INVALID = -1
)

func IntToCode(se Second)string { ... }
func CodeToInt(code string)Second { ... }

example.go

package mypackage

import (
    "first"
    "second"
)

First fi = first.CodeToInt("ConstOne")
Second se = SE_INVALID

什么是更好,更惯用的解决方案?我喜欢能够说出这样的话:

First fi = First.Invalid

但是我还没有成功地提出一种允许这样做的方法。

1 个答案:

答案 0 :(得分:0)

您可以为单独的代码集和单个包提供单独的包,用于定义与代码相关的更高级功能以及为更高级别的包编写测试。

我没有编译或测试任何这些:

E.g。代码集:

package product // or whatever namespace is associated with the codeset

type Const int

const (
    ONE Const = iota
    TWO
    ...
    INVALID = -1
)

func (c Const) Code() string {
    return intToCode(int(c)) // internal implementation
}

type Code string

const (
     STR_ONE Code = "ONE"
     ...
)

func (c Code) Const() int {
    return codeToInt(string(c)) // internal implementation
}

E.g。对于更高级别的功能包:

// codes.go
package codes

type Coder interface{
    Code() string
}

type Conster interface{
    Const() int
}

func DoSomething(c Coder) string {
    return "The code is: " + c.Code()
}    

// codes_product_test.go
package codes

import "product"

func TestProductCodes(t *testing.T) {
    got := DoSomething(product.ONE) // you can pass a product.Const as a Coder
    want := "The code is: ONE"
    if got != want {
        t.Error("got:", got, "want:", want)
    }
}

修改

要检索特定代码的const,您可以执行类似

的操作
product.Code("STRCODE").Const()

如果Const()返回Coder,以便product.Code("ONE").Const()可以是product.Const,也许会更好。我想如果你玩它有一些选择,那里会有一个很好的选择。