如何在Golang中通过接口字段类型访问底层结构字段的值?

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

How to access underlying struct field value if via interface field type in Golang?

问题

通过接口直接获取结构字段值是不可能的,但是有一些技巧可以实现。

在文件"./animals/mammal.go"中,你定义了一个接口"Mammal":

type Mammal interface {
    Sound()
}

在同一个文件中,你实现了一个结构体"Dog":

type Dog struct {
    Name string
    Age  int
}

func (d *Dog) Sound() {
    fmt.Println("Say my name...", d.Name)
}

在另一个包"../../police/animals.go"中,你有另一个结构体"Policeman":

type Policeman struct {
    Animal    Mammal
    Policeman Name
    ID        int
}

你希望能够像这样实现它:

func (p *Policeman) Arrest() {
    fmt.Println("Hands up, police! Bite him, ", p.Animal.Name)
}

但是编译器不允许这样做,因为"p.Animal"是一个接口类型。
然而,有一种应用设计技巧/模式可以实现你的需求。我的观点是,一旦我写了"Policeman"结构体,我希望确保当我将动物从狗改为猫或其他动物时,我不需要重写"Arrest"方法。这就是问题的关键所在!

英文:

Is there some trick (it is impossible directly) on how to get struct field values via interface?

I have an interface in a file ./animals/mammal.go:

type Mammal interface {
     Sound()
}

I have implementation in the same file:

type Dog struct {
     Name string
     Age int
}

func (d *Dog) Sound {
     fmt.Println("Say my name...", d.Name)
}

In other package ../../police/animals.go I have another struct:

type Policeman struct {
     Animal Mammal
     Policeman Name
     ID int
}

And I wish to be able to implement it like this:

func (p *Policeman) Arrest {
     fmt.Println("Hands up, police! Bite him, ", p.Animal.Name)
}

And compiler won't let me do that, because p.Animal is an interface type, of course...
However, is there an application design trick/pattern, that could allow me to do that. My point is, that once I wrote Policeman struct, I wish to be sure, that WHEN I CHANGE an animal from Dog to Cat or somebody else, I won't rewrite the "Arrest" method, so that's the point of the question!

答案1

得分: 1

如果在你的上下文中,以下陈述是真实的:“所有哺乳动物都有一个名字”,你可以在接口Mammal中添加一个方法Name(),你的示例将像这样工作:

type Mammal interface {
     Sound()
     Name() string
}

func (p *Policeman) Arrest {
     fmt.Println("Hands up, police! Bite him, ", p.Animal.Name())
}

如果这个陈述不是真实的,那么你想要的是不可能的,因为对于没有名字的哺乳动物调用Name()方法的处理方式仍然不清楚。

请注意,你还需要为Dog实现Name()方法。

英文:

If, in your context, the following statement is true "All mammals have a name", you can add a method Name() to the interface Mammal and your example would work like this:

type Mammal interface {
     Sound()
     Name() string
}

func (p *Policeman) Arrest {
     fmt.Println("Hands up, police! Bite him, ", p.Animal.Name())
}

If the statement is not true, then want you want is impossible because it remains unclear what to do with a call to Name() for a mammal that does not have a name.

Note that you then also need to implement the Name() method for Dog.

huangapple
  • 本文由 发表于 2022年4月30日 21:26:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/72068901.html
匿名

发表评论

匿名网友

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

确定