Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何获取父嵌入结构字段值?_Go - Fatal编程技术网

Go 如何获取父嵌入结构字段值?

Go 如何获取父嵌入结构字段值?,go,Go,我的包中有以下结构 type Animal struct { Id string // and some more common fields } 使用我的软件包的用户应该能够实现自己的动物。由于我的一个方法需要Id,用户必须嵌入我的结构 type Dog struct { Animal Name string Legs int } 在我的软件包中,我有一个保存功能,可以将动物保存到数据库中。因为我不知道用户的类型,所以必须使用接口{}作为参数类型。我的问题是:如何从父结

我的包中有以下结构

type Animal struct {
  Id string
  // and some more common fields
}
使用我的软件包的用户应该能够实现自己的动物。由于我的一个方法需要Id,用户必须嵌入我的结构

type Dog struct {
  Animal
  Name string
  Legs int
}
在我的软件包中,我有一个保存功能,可以将动物保存到数据库中。因为我不知道用户的类型,所以必须使用接口{}作为参数类型。我的问题是:如何从父结构动物获取Id?目前,我使用了一些JSON解析和解组,但这是go/go的方法吗

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
  // ...
}
用法


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

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())
}
请参阅中的完整示例

输出:

&{{dogid} wouf 0}
&{dogid}
更简单:

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

您可以使用这个小的反射技巧来实现,尽管使用@VonC建议的接口可能是一种更实用、更惯用的方法

不管怎么说,反射也可以实现同样的效果:

func main() {

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

这里的方法是将Animal声明为接口:

type Animal interface {
    ID() int
    Name() string
    // Other Animal field getters here.
}
然后,save可以将Animal作为参数,并使用Animal的方法获取它需要的所有信息


另一种可能的方法是使用包从结构中获取动物场,但这将比使用接口更麻烦、更脏,而且可能更慢。

为什么不让saveAnimalGetter保存施法?@不是高尔夫球手确定,我只是使用了问题中提到的签名或saveinterface{}。我已经按照你的建议编辑了答案。小挑剔:getter应该被称为Animal,而不是GetAnimal。@VonC你的方法甚至可以通过使动物本身成为animalGetter来简化,然后不需要为每个动物重新实现此功能。以下是我对您建议的看法:@Ainar-G我尝试过给它命名为动物,但失败了,使用了一个Dog-field动物和一个Dog-method动物:重复的名称使编译变得不可能。一开始我避免了思考,更喜欢让API需要让动物更可见。但反思当然可以奏效。
type Animal interface {
    ID() int
    Name() string
    // Other Animal field getters here.
}