如何获取父嵌入式struct字段值?

时间:2014-09-08 14:11:00

标签: go

我的包中有以下结构。

type Animal struct {
  Id string
  // and some more common fields
}

使用我的包的用户应该能够实现自己的Animal。由于我在我的一种方法中需要Id,因此用户必须嵌入我的结构。

type Dog struct {
  Animal
  Name string
  Legs int
}

在我的包中,我有save()函数将Animal保存到数据库。由于我不知道用户的类型,我必须使用interface{}作为参数类型。我的问题是:如何获取Id(来自父结构Animal)?目前我使用了一些JSON解析和解组,但这是去/去的方式吗?

func put(doc interface{}) error {
  res, err := json.Marshal(doc)
  if err != nil {
    return err
  }
  var animal *Animal
  err = json.Unmarshal(res, &animal)
  if err != nil {
    return err
  }
  fmt.Println(animal.Id) // finally I have the Id
  // ...
}

用法

func main() {
  bello := Dog{
    Animal: Animal{
      Id: "abcd1234",
    },
    Name: "bello",
    Legs: 4,
  }
  err := put(bello)
  // ...
}

3 个答案:

答案 0 :(得分:2)

也许你可以添加一个接口,以确保获得对父结构的引用:

type AnimalGetter interface {
    GetAnimal() *Animal
}

func (dog *Dog) GetAnimal() *Animal {
    return &dog.Animal
}

这将允许你的save方法做一个类型断言(AnimalGetter):

func save(obj interface{}) {
    animal := obj.(AnimalGetter)
    fmt.Printf("%v\n", animal.GetAnimal())
}

请参阅 play.golang.org 中的完整示例。

输出:

&{{dogid} wouf 0}
&{dogid}

简单:

func save(animal AnimalGetter) {
    fmt.Printf("%v\n", animal.GetAnimal())
}

play.golang.org

答案 1 :(得分:2)

去/去的方法是将Animal声明为接口:

type Animal interface {
    ID() int
    Name() string
    // Other Animal field getters here.
}

然后,save可以将Animal作为参数,并使用Animal的方法获取所需的所有信息。

另一种可能的方法是使用reflect包来从结构中获取Animal字段,但这将使用界面更加笨拙,更脏并且可能更慢。

答案 2 :(得分:1)

你可以用这个小的反射技巧来做到这一点,尽管使用像@VonC建议这样的接口可能是一种更实用和惯用的方法。

无论如何,这与反射相同:

func main() {

    d := Dog {
        Animal { "id1111" },
        "Barky",
        4,
    }
    fmt.Println(reflect.ValueOf(d).FieldByName("Animal").Interface().(Animal))
}