几个月来,我一直在空闲时间断断续续地使用 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/