Struct 嵌入式结构方法是否可以了解父/子结构?

Struct 嵌入式结构方法是否可以了解父/子结构?,struct,go,embedding,Struct,Go,Embedding,几个月来,我一直在空闲时间断断续续地和Go一起工作,我觉得我已经掌握了其中的窍门。来自传统的OOP语言,如Java和PHP,我很难掌握Go的组成和嵌入。我想它最近终于点击了,我想更多地使用它,但我有一个想法遇到了障碍 假设我有一个来自一个包的结构,该包有一个Validate方法,我将它嵌入到我当前工作的包的结构中。是否有一种方法(我拥有这两个包)可以获得对正在验证方法内部进行嵌入的结构的引用?有点像是一种看谁给我打电话的方式,因为我会在“家长”而不是嵌入式系统上打电话 我会尝试想象这个 type

几个月来,我一直在空闲时间断断续续地和Go一起工作,我觉得我已经掌握了其中的窍门。来自传统的OOP语言,如Java和PHP,我很难掌握Go的组成和嵌入。我想它最近终于点击了,我想更多地使用它,但我有一个想法遇到了障碍

假设我有一个来自一个包的结构,该包有一个Validate方法,我将它嵌入到我当前工作的包的结构中。是否有一种方法(我拥有这两个包)可以获得对正在验证方法内部进行嵌入的结构的引用?有点像是一种看谁给我打电话的方式,因为我会在“家长”而不是嵌入式系统上打电话

我会尝试想象这个

type B struct {}
func (b B) Validate() {
  // get reference somehow of A obj
}


type A struct {
  B
}

a := A{B{}}
a.Validate()

我觉得这似乎是不可能的,但如果你可以的话,那就太酷了。我想您需要使A和B都具有相同的接口类型才能工作。任何想法或帮助都将不胜感激。

任何形式的
家长
参考都是不可能的。你希望对父母做什么?因为它们可能是非常不同的类型,所以它们不兼容,无法做任何有意义的事情

如果您需要不同类型之间的共同点,您需要一个接口,并且需要传入:

type B struct {}
func (b B) Validate(parent MyInterface) {
}


type A struct {
  B
}
// A implements MyInterface
a := A{B{}}
a.Validate(a)

如果你能解释一下你真正想要实现的目标,那么几乎可以肯定有比这更好的方法

这是不可能的。为了更好地理解原因,请参阅您的示例的这个稍加修改的版本:

type B struct{}

func (b *B) Validate() {
    fmt.Printf("b:%p\n", b)
}

type A struct {
    *B
}

func main() {
    b := B{}
    a1 := A{&b}
    a2 := A{&b}

    a1.Validate()
    a2.Validate()
    a1.B.Validate()
    a2.B.Validate()

    b.Validate()
}
输出与预期相同,
*B
的值无处不在():

如您所见,我将方法接收器和嵌入类型更改为指针
B

从这个例子中可以清楚地看到:您可以使用相同的
B
(或者更确切地说是相同的
B
)值地址来嵌入不同类型的
a

并且您可以对这两种方法调用
Validate()
:因此,对于给定的
*B
值,理论上的“父级”甚至不是“常量”,这不会破坏交易,但是:如果值为
a
,您可以通过编写
a.Validate()
调用提升的方法
B.Validate()
,这是可以的,但是你也可以像调用
a.B.Validate()
-现在你没有真正的
a
(有争议,但是
Validate()
调用的是
*B
而不是
a
),但是最后你也可以调用
B.Validate()
-这次您肯定没有
a
的值

父级没有明确的类型,
B
(或
*B
)可以嵌入到任何类型中(因此它只能是
接口{}

如图所示:您有一个具体的值
*B
,当调用它的
Validate()
方法时,有时有父对象,有时没有父对象。那么,有父母的理由是什么呢

回到您的示例:对于此
Validate()
方法来验证有意义的内容,它应该(必须)作为参数显式地而不是自动地传递给
Validate()
方法

你所能做的就是captncraig在(+1)中所写的内容

但是,如果显式地向
a
添加一个方法,该方法将调用
B.Validate()
,如下所示:

func (a *A) Validate2() {
    a.Validate(a)
}

// And using it:
a.Validate2()

对于您想象嵌入
a
中的那种验证器没有任何理由,它应该只是
a
的一个字段,或者由于没有直接关系,它可以是一个“独立”验证器。在这两种情况下,如果希望简化验证,您可以向
a
添加一个helper
Validate()
方法。

目前,我有一个类似于Java中HIbernate验证的验证库。到目前为止,我有一个您使用的验证方法,如您所建议的:mypackage.validate(myStructOb)。如果有一种方法可以在我想要验证的结构上嵌入一个validate方法并调用它,我会认为它会更干净。我在Java API索引中找不到关于Hibernate的任何信息,所以我不知道你想做什么。我要重申这一答复的第一段。
验证
需要了解嵌入它的结构的哪些功能?
func (a *A) Validate2() {
    a.Validate(a)
}

// And using it:
a.Validate2()