确定var是否为自定义类型

时间:2014-09-27 04:04:20

标签: types go assertions

如何确定传递给我的Func的var实际上是否是我想要的Type?

我有自定义类型

type Name string

和一堆那种类型的常量

const Fred Name = "fred"

我有一个func,我需要禁止除我的自定义类型ex以外的任何其他类型的输入:

func MyFunc(name1 Name, name2 Name) (*Person, error) {
//bunch of stuff
}

我如何在我的func中检查name1和name2是不是传递给func的字符串,而是仅在我的类型ex中定义的const:

p, err := MyFunc(Fred,Albert) //What i want
p, err := MyFunc("fred","albert") //What i dont want to happen

如果无法回答我的问题,我怎么能像Golang中的Enum那样做一个意味着什么的类型并限制其他人使用我定义的类型

2 个答案:

答案 0 :(得分:4)

让你的类型实现一个未导出的界面

type Name string

type Private interface{
     private()
}

func (n Name) private() {}

func MyFunc(name1, name2 Private) (*Person, error) {
    //bunch of stuff
}

答案 1 :(得分:1)

短版?你不能创造那种限制性的枚举。

长版本,选项很少:

在"类型":

上定义验证功能
func (n Name) valid() bool { //private method
    switch n {
    case Mal, Kaylee: //all the valid constants
        return true
    }
    return false
}

然而,这并不能阻止某人像@peterSO指出的那样使用Name("fred").valid()

使用包含私有成员的结构,但它们不是"常数"本身,外部包可以将它们重新分配给无效值:

type Name struct {
    n string
}

var (
    invalid = Name{}
    Mal     = Name{"mal"}
    Kaylee  = Name{"kaylee"}
)

func MyFunc(name1 Name, name2 Name) error {
    if name1 == invalid || name2 == invalid {
        return errors.New("invalid names")
    }
    return nil
}

使用数字常量和私有数组,这是真正唯一的万无一失的版本,并且您将获得真正的枚举:

type Name uint8

var names = [...]string{
    "Mal",
    "Kaylee",
}

func (n Name) valid() bool {
    return uint8(n) < uint8(len(names))
}

func (n Name) String() string {
    if !n.valid() {
        return "invalid"
    }
    return names[n]
} 

const (
    Mal Name = iota
    Kaylee
)

func MyFunc(name1 Name, name2 Name) error {
    if !name1.valid() || !name2.valid() {
        return errors.New("invalid names")
    }
    return nil
}
相关问题