英文:
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("fred").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{"mal"}
	Kaylee  = Name{"kaylee"}
)
func MyFunc(name1 Name, name2 Name) error {
	if name1 == invalid || name2 == invalid {
		return errors.New("invalid names")
	}
	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{
	"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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论