golang有两种带有一个字段的切片类型。

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

golang 2 slice types with 1 field

问题

鉴于 golang 不支持联合类型,实现上述需求的最佳方式是什么?

type foo struct {
    words []string
    nums []int
}

这样只能同时使用 wordsnums。我尝试过以下方法:

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

注意:

  1. Foo不能是接口类型(类型Foo []interface{}或类型Foo interface{}),但可以是包含接口类型的结构体。

  2. 你也不能将[]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:

  1. Foo cannot be an interface type (type Foo []interface{} or type Foo interface{}) but can be a struct which contains an interface type.

  2. You also cannot assert []interface{} to another slice type as an []interface{} is a type in its own right. See here

huangapple
  • 本文由 发表于 2014年7月28日 03:13:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/24984619.html
匿名

发表评论

匿名网友

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

确定