如何通过嵌入式接口嵌入struct值:Composable Structs

时间:2016-03-10 21:51:47

标签: go struct

这个问题最好用一个例子来描述

http://play.golang.org/p/bQuRr0kV-b

我正在尝试创建一个可组合的结构。在这个例子中,我希望有一个Person类型,其中包含来自Female或Male的嵌入值。如果我只是处理结构,我会像这样嵌入它们

type Person Struct{
  Female
  Male
}

我不能这样做,因为在实际项目中,有很多嵌入式结构,我宁愿保持结构清洁和可组合。但是也存在命名冲突 - 在这个例子中,男性和女性都包含“眼睛”字段。将冲突值移动到Person结构不是一个可行的解决方案(因为许多其他嵌入式结构不包含该特定值)。

我希望通过简单的界面传递这些值。下面的示例:运行此代码时,我得到&{Name: Age:0 Type:male GenderType:0x10434120}其中GenderType是指向Male结构的指针(在本例中)。我的目标是返回一个看起来像&{Name: Age:0 Type:male Eyes: ChestSize:0}

的扁平结构
package main

import "fmt"

type Person struct {
    Name string
    Age  int
    Type string
    GenderType 
}

type GenderType interface {
    TypeName() string
}

type Male struct {
    Eyes     string
    ChestSize int
}

type Female struct {
    Eyes string
    BustSize int
}

func (m *Male) TypeName() string {
    return "male"
}

func (f *Female) TypeName() string {
    return "female"
}

func main() {

    d := NewHuman(new(Male))
    fmt.Printf("%+v", d)
}

func NewHuman(gt GenderType) *Person {
    return &Person{
        Type: gt.TypeName(),
        GenderType: gt,

    }
}

1 个答案:

答案 0 :(得分:2)

我不认为可以在平面结构中执行此操作,因为它需要在运行时更改结构类型的内存结构,这是不允许的。虽然您可以使用GenderType访问嵌入字段,但它仍然是允许的,因为您说这将是对满足接口的嵌入式结构的引用,而不是更改结构本身的结构。

我认为使用此方法编组成平面json的更好方法是保留嵌入式结构,但然后使Person结构成为Marshaler

您可以添加自己的自定义MarshalJSON()(byte [],error)方法,并使用它来生成平面json输出。

如果您需要专门的解组,那么您也可以使用与Person关联的(UnmarshalJSON([] byte)错误)方法。

请参阅https://golang.org/pkg/encoding/json/#Marshaler以获取进一步的参考资料

这是一个展示我的意思的游乐场:https://play.golang.org/p/qOl9WSaI3O