为了账号安全,请及时绑定邮箱和手机立即绑定

Go 中具有作用域的多组常量名称

Go 中具有作用域的多组常量名称

Go
杨__羊羊 2021-11-29 19:36:26
我有一个需要无限数量的常量集的 Go 应用程序。该应用程序还要求我能够在运行时将字符串映射到(整数)常量,反之亦然。常量的名称只能保证是有效的标识符,因此几乎可以肯定会有重复的常量名称。特别是,每组常量都有一个称为“无效”的元素。在 C++11 中,我会使用枚举类来实现作用域。在 Python 中,我可能会使用类变量。我正在努力寻找一种在 Go 中表达这一点的惯用方式。我看过的选项包括:为每组常量使用单独的包。这有很多缺点,因为我宁愿整个集合都在同一个包中,这样我就可以在包级别构建对这些集合的支持,这样我就可以测试整个集合,而不会使测试代码过于复杂一次进行多包测试。first.go:package firsttype First intconst (    ConstOne First = iota    ConstTwo    Invalid = -1)func IntToCode(fi First)string { ... }func CodeToInt(code string)First { ... }second.go:package secondtype Second intconst (    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对每个常量使用经过验证的全局唯一前缀技术。然而,考虑到集合的数量真的很大,必须使用编码约定从本质上发明和管理一堆命名空间充其量是尴尬的。此选项还迫使我修改常量的名称(这是使用它们的全部意义)。first.go:package mypackagetype First intconst (    FI_CONSTONE First = iota    FI_CONSTTWO    FI_INVALID = -1)func IntToCode(fi First)string { ... }func CodeToInt(code string)First { ... }second.go:package mypackagetype Second intconst (    SE_CONSTONE Second = iota    SE_CONSTTWO    SE_INVALID = -1)func IntToCode(se Second)string { ... }func CodeToInt(code string)Second { ... }example.go:package mypackageimport (    "first"    "second")First fi = first.CodeToInt("ConstOne")Second se = SE_INVALID什么是更好、更惯用的解决方案?我希望能够说这样的话:First fi = First.Invalid但我没有成功地提出一种允许这样做的方法。
查看完整描述

1 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

您可以为单独的代码集使用单独的包,并使用单个包来定义与代码关联的更高级别的功能,并为该更高级别的包编写测试。


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


例如对于代码集:


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

}

例如对于更高级别的函数包:


// 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)

    }

}

编辑:


要检索特定代码的常量,您可以执行以下操作


product.Code("STRCODE").Const()

也许最好Const()返回 aCoder以便product.Code("ONE").Const()可以是 a product.Const。我认为如果你玩弄它,有几种选择,并且在某个地方会有一个很好的选择。


查看完整回答
反对 回复 2021-11-29
  • 1 回答
  • 0 关注
  • 169 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信