Use a foo
package to hide the implementation. For example,
package foo
const (
typeWords = iota + 1
typeNums
)
type Foo struct {
fooType byte
words []string
nums []int
}
func NewWords(words []string) *Foo {
return &Foo{fooType: typeWords, words: words}
}
func NewNums(nums []int) *Foo {
return &Foo{fooType: typeNums, nums: nums}
}
func (f *Foo) Words() []string {
if f.fooType != typeWords {
return nil
}
return f.words
}
func (f *Foo) Nums() []int {
if f.fooType != typeNums {
return nil
}
return f.nums
}
ADDENDUM:
Since we are hiding the implementation of package foo
, we can implement it another way. For example, we could adopt twinj's suggestion and use an interface. To ensure some degree of generality, let's add another []string
type Phrases
. The value types are used to distinguish between the two []string
types.
package foo
type (
valueWords []string
valuePhrases []string
valueNums []int
)
type Foo struct {
value interface{}
}
func NewWords(words []string) *Foo {
return &Foo{value: valueWords(words)}
}
func (f *Foo) Words() []string {
value, ok := f.value.(valueWords)
if !ok {
return nil
}
return value
}
func NewPhrases(phrases []string) *Foo {
return &Foo{value: valuePhrases(phrases)}
}
func (f *Foo) Phrases() []string {
value, ok := f.value.(valuePhrases)
if !ok {
return nil
}
return value
}
func NewNums(nums []int) *Foo {
return &Foo{value: valueNums(nums)}
}
func (f *Foo) Nums() []int {
value, ok := f.value.(valueNums)
if !ok {
return nil
}
return value
}