struct - 嵌入式结构方法可以了解父/子吗?

标签 struct go embedding

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

假设我有一个包中的结构,该结构具有 Validate 方法,我将其嵌入到我当前正在使用的包中的结构中。有没有一种方法(我拥有两个包)可以获得对在 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 都成为相同的接口(interface)类型才能工作。任何想法或帮助将不胜感激。

最佳答案

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

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 值 (Go Playground):

b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8
b: 0x1becd8

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

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

并且您可以对两者都调用 Validate():因此对于 *B 的给定值,理论上的“父级”甚至不是“常量”。 这不会破坏交易,但是:具有 A 的值,您可以通过编写 B.Validate() 调用提升的方法 a.Validate() 没问题,但您也可以像 a.B.Validate() 这样调用它 - 现在您实际上没有 A 的值(有争议,但是 Validate() 是在 *B 而不是 A 的值上调用的),但最后你也可以调用 b.Validate() - 这次您绝对没有 A 的值。

父级没有确定的类型,B(或*B)可以嵌入任何类型(所以它只能是接口(interface){})。

所以图像:你有一个具体的值 *B 并且当它的 Validate() 方法被调用时,有时有父级,有时没有.那么有 parent 的理由是什么?

回到您的示例:对于此 Validate() 方法来验证有意义的内容,它应该(必须)作为参数传递给 Validate() 方法 -明确而非自动。

你能做的就是 captncraig 在 his answer 中写的(+1)。

你可以稍微简化它,如果你显式地向 A 添加一个方法,它会像这样调用 B.Validate():

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

// And using it:
a.Validate2()

没有理由将您想象的那种嵌入到 A 中的验证器,它应该只是 A 的一个字段,或者因为没有直接的关系,它可以是一个“独立”的验证器。在这两种情况下,如果您想简化验证,您可以向 A 添加辅助方法 Validate()

关于struct - 嵌入式结构方法可以了解父/子吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30622605/

相关文章:

c - 如何仅使用指针运算访问结构中的数组

go - 仅当 Google 数据存储区中不存在该键时才写入实体

performance - 将 MeiYan 哈希函数移植到 Go

json - MarshalJSON 具有嵌入式类型的类型以 {} 而不是值结束

elasticsearch - 全文和 knn_vector 混合搜索弹性

c - 将带有 void 指针参数的函数指针传递给函数

c# - 从结构中读取双字段

c - 释放链表中的节点

go - 通过将空结构传递到 channel Go 来停止循环

actionscript-3 - 在 Flash 动画中嵌入 LaTeX 内容