英文:
golang 2 slice types with 1 field
问题
鉴于 golang 不支持联合类型,实现上述需求的最佳方式是什么?
type foo struct {
words []string
nums []int
}
这样只能同时使用 words
或 nums
。我尝试过以下方法:
type foo struct {
values []interface{}
}
但我更喜欢一种限制类型为上述两种类型或带有指针的方法。
英文:
In light of the fact that golang does not support unions, what is the best way to achieve:
type foo struct {
words []string
nums []int
}
such that only words
or nums
can be used at once. One thing I've tried is:
type foo struct {
values []interface{}
}
but I prefer something that restricts the types to the two mentioned or something with pointers.
答案1
得分: 3
使用foo
包来隐藏实现细节。例如,
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
}
补充说明:
由于我们隐藏了foo
包的实现细节,我们可以采用另一种方式实现。例如,我们可以采纳twinj的建议并使用接口。为了确保一定程度的通用性,让我们再添加一个[]string
类型的Phrases
。值类型用于区分这两种[]string
类型。
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
}
英文:
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
}
答案2
得分: 3
另一种选择是使用接口和类型断言。
type Foo struct {
values interface{}
}
func (o *Foo) Words() []string {
if v, ok := o.values.([]string); ok {
return v
}
return nil
}
func (o *Foo) Nums() []int {
if v, ok := o.values.([]int); ok {
return v
}
return nil
}
请查看Go Playground示例:GoPlay
注意:
-
Foo不能是接口类型(类型Foo []interface{}或类型Foo interface{}),但可以是包含接口类型的结构体。
-
你也不能将[]interface{}断言为另一个切片类型,因为[]interface{}本身就是一种类型。在这里查看
英文:
Another option would be to use an interface and type assertion.
type Foo struct {
values interface{}
}
func (o *Foo) Words() []string {
if v, ok := o.values.([]string); ok {
return v
}
return nil
}
func (o *Foo) Nums() []int {
if v, ok := o.values.([]int); ok {
return v
}
return nil
}
Check out the Go playground example: GoPlay
Note:
-
Foo cannot be an interface type (type Foo []interface{} or type Foo interface{}) but can be a struct which contains an interface type.
-
You also cannot assert []interface{} to another slice type as an []interface{} is a type in its own right. See here
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论