2014-09-27 3 views
3

Как определить, действительно ли переменная, переданная в мой Func, тип, который я хочу?Определить, является ли var нестандартным Тип

У меня есть пользовательский тип

type Name string 

и куча констант этого типа

const Fred Name = "fred" 

и у меня есть FUNC, что мне нужно, чтобы запретить любой другой тип входа, кроме моего обычая Тип ex:

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

как я проверяю внутри своей функции, что имя1 и имя2 не являются строками, переданными функции но исключительно сопзИте я уже определен в моем типе е:

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

если не может ответить на мой вопрос, как я могу сделать, как Enum в Golang типа А это означает, что что-то и ограничить другие госзакупки использовать этот тип я определен

ответ

1

Краткая версия? вы не можете создать этот ограничивающий тип перечисления.

Длинная версия, есть несколько вариантов:

Определить функцию проверки на «тип»:

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

Это, однако, не мешает кому-то использовать Name("fred").valid() как @peterSO указал.

Используйте-структуру с собственным членом в нем, однако они не являются «константой» на-с, внешний пакет может переназначить их недопустимые значения:

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 
} 
+1

Наконец, это было правильное решение, все значения, которые мне нужны, должны быть константами, поэтому я применил последнюю из ваших рекомендаций, другие ответы не передали goLint и ни то, где определенно решалось как последнее из ваших предложений, thanks – Eefret

4

ваш типу реализовать интерфейс, который не экспортированный

type Name string 

type Private interface{ 
    private() 
} 

func (n Name) private() {} 

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

Это очень сложная идея, хотя и добавляет накладные расходы во время выполнения интерфейса. +1 тем не менее. – OneOfOne

+0

@OneOfOne Я полагаю, вы также можете иметь private() return Name для удобства 'interface private {private() Name}'. – jmaloney

+0

Я не уверен на 100%, но я * думаю * просто передача интерфейса сама по себе требует накладных расходов во время выполнения, но я могу ошибаться. – OneOfOne