确定 var 是否为自定义类型

huangapple go评论89阅读模式
英文:

Determine if var is a custom Type

问题

如何确定传递给我的函数的变量实际上是我想要的类型?

我有一个自定义类型:

type Name string

还有一堆该类型的常量:

const Fred Name = "fred"

我需要在一个函数中禁止除了我自定义类型之外的任何其他类型的输入,例如:

func MyFunc(name1 Name, name2 Name) (*Person, error) {
    // 一堆操作
}

我如何在我的函数内部检查name1和name2不是作为字符串传递给函数的,而是我已经在我的类型中定义的常量,例如:

p, err := MyFunc(Fred, Albert) // 这是我想要的
p, err := MyFunc("fred", "albert") // 这是我不想要发生的

如果无法回答我的问题,我如何在Golang中创建一个类似于枚举的类型,表示某个含义并限制其他人使用我定义的类型?

英文:

How to determine if the var passed to my Func is actually the Type that i want?

i have a custom Type

type Name string

and a bunch of constants of that type

const Fred Name = "fred"

and i have a func that i need to forbid any other type of input other than my custom Type ex:

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

how i check inside my func that name1 and name2 are not strings passed to the func but exclusively the const i already defined in my type ex:

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

if cannot answer my question how i can make like a Enum in Golang a type that means something and restrict other ppl to use that type i defined

答案1

得分: 4

你的代码如下所示:

type Name string

type Private interface {
    private()
}

func (n Name) private() {}

func MyFunc(name1, name2 Private) (*Person, error) {
    //一堆代码
}

你想让Name类型实现一个未导出的接口Private,并在MyFunc函数中使用这个接口作为参数。

英文:

have your type implement an interface that is not exported

type Name string

type Private interface{
     private()
}

func (n Name) private() {}

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

答案2

得分: 1

简化版本?你不能创建那种限制性的枚举。

长版本,有几个选项:

在"type"上定义一个验证函数:

func (n Name) valid() bool { //私有方法
    switch n {
    case Mal, Kaylee: //所有有效的常量
        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
}
英文:

Short version? you can't create that restricting kind of enum.

Long version, there are few options:

Define a validation function on the "type":

func (n Name) valid() bool { //private method
	switch n {
	case Mal, Kaylee: //all the valid constants
		return true
	}
	return false
}

This however doesn't stop someone from using Name(&quot;fred&quot;).valid() like @peterSO pointed out.

Use a struct with a private member in it, however they aren't "constants" per-se, an outside package can reassign them to invalid values:

type Name struct {
	n string
}

var (
	invalid = Name{}
	Mal     = Name{&quot;mal&quot;}
	Kaylee  = Name{&quot;kaylee&quot;}
)

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

Use numeric constants and a private array, this is the only fool-proof version really and the closest you will get to a real enum:

type Name uint8

var names = [...]string{
	&quot;Mal&quot;,
	&quot;Kaylee&quot;,
}

func (n Name) valid() bool {
	return uint8(n) &lt; uint8(len(names))
}

func (n Name) String() string {
	if !n.valid() {
		return &quot;invalid&quot;
	}
	return names[n]
} 
 
const (
	Mal Name = iota
	Kaylee
)

func MyFunc(name1 Name, name2 Name) error {
	if !name1.valid() || !name2.valid() {
		return errors.New(&quot;invalid names&quot;)
	}
	return nil
}

huangapple
  • 本文由 发表于 2014年9月27日 12:04:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/26071173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定