Inheritance 嵌套结构-get";“基础”;结构

Inheritance 嵌套结构-get";“基础”;结构,inheritance,struct,go,nested,Inheritance,Struct,Go,Nested,(作为后续问题:) 现在,我可以使用易于编写的文本初始化结构,我稍后在代码中需要访问父结构的成员,但不知道具体的派生类型。是这样的: type A struct { MemberA string } type B struct { A MemberB string } b := B { A: A { MemberA: "test1" }, MemberB: "test2", } fmt.Printf("%+v\n", b) var i interfa

(作为后续问题:)

现在,我可以使用易于编写的文本初始化结构,我稍后在代码中需要访问父结构的成员,但不知道具体的派生类型。是这样的:

type A struct {
    MemberA string
}

type B struct {
    A
    MemberB string
}
b := B {
    A: A { MemberA: "test1" },
    MemberB: "test2",
}
fmt.Printf("%+v\n", b)

var i interface{} = b

// later in the code, I only know that I have something that has a nested A,
// I don't know about B (because A is in a library and B is in the 
// calling code that uses the library).

// so I want to say "give me the A out of i", so I try a type assertion

if a, ok := i.(A); ok {
    fmt.Printf("Yup, A is A: %+v\n", a)
} else {
    fmt.Printf("Aristotle (and John Galt) be damned! A is NOT A\n")
}

// no go
然后我就这样使用它:

type A struct {
    MemberA string
}

type B struct {
    A
    MemberB string
}
b := B {
    A: A { MemberA: "test1" },
    MemberB: "test2",
}
fmt.Printf("%+v\n", b)

var i interface{} = b

// later in the code, I only know that I have something that has a nested A,
// I don't know about B (because A is in a library and B is in the 
// calling code that uses the library).

// so I want to say "give me the A out of i", so I try a type assertion

if a, ok := i.(A); ok {
    fmt.Printf("Yup, A is A: %+v\n", a)
} else {
    fmt.Printf("Aristotle (and John Galt) be damned! A is NOT A\n")
}

// no go
我看到的选择是:

  • 我可以使用反射来查找名为“a”的成员,并假设它是正确的类型,使用它。这将是可行的,但效率较低,当然更“笨重”

  • 我可以要求调用方实现一个接口(比如
    HasA{Aval()A}
    或类似的接口,它返回一个A的实例。到目前为止,这是我能想到的最好的主意

  • 另一点是,我可以让调用者传递一个a值(即在上面的例子中,
    vari接口{}=b
    变成
    vari a=b.a
    )。但是实际上,我动态地迭代了b的成员,并对它们进行处理,所以我需要更多的“派生”类型来实现这一点。(我在问题中省略了这一点,因为这只是我为什么会遇到这个问题的背景,与问题的技术答案无关。)


如果我能像您在Java中那样“将其转换为A”,那就太好了。有没有更优雅的方法可以做到这一点。

这对我来说很有效。虽然它不像您希望的那样直接转换,但它确实提供了正确的对象实例

fmt.Printf("It's", i.(B).A)

我希望它能帮上忙!

这对我来说很有效。虽然它没有像你想要的那样直接施放,但它确实给出了正确的对象实例

fmt.Printf("It's", i.(B).A)

我希望它能有所帮助!

如果您有未知的类型b,那么挖掘嵌入字段的唯一方法就是通过反射

没那么笨重:

结构嵌入不是继承,尝试这样使用它将继续带来类似的问题。在go中实现通用多态性的方法是使用接口


我认为处理这种情况最干净的方法是使用一个公共接口,为您想要处理的字段提供适当的访问器方法。您将在stdlib中看到这方面的示例,例如
http.ResponseWriter
,它有一个
头()
用于访问实际响应头的方法。

如果您有未知的类型b,则挖掘嵌入字段的唯一方法是通过反射

没那么笨重:

结构嵌入不是继承,尝试这样使用它将继续带来类似的问题。在go中实现通用多态性的方法是使用接口


我认为处理这种情况最干净的方法是使用一个公共接口,为您想要处理的字段提供适当的访问器方法。您将在stdlib中看到这方面的示例,例如
http.ResponseWriter
,它有一个
头()
用于访问实际响应头的方法。

我对它进行了一段时间的研究,我得到了以下结果:

我不能百分之百确定为什么会这样,但我最好的理论是,当你打电话的时候

a := i.(A)
您正在尝试对存储在
i
a
中的任何内容进行界面版本的类型转换。因此,您首先需要告诉它实际上是
B
,然后您可以访问嵌套在其中的a

a := i.(B).A

玩了一会儿,我就成功了:

我不能百分之百确定为什么会这样,但我最好的理论是,当你打电话的时候

a := i.(A)
您正在尝试对存储在
i
a
中的任何内容进行界面版本的类型转换。因此,您首先需要告诉它实际上是
B
,然后您可以访问嵌套在其中的a

a := i.(B).A
如果我能像你在Java中所做的那样“把它转换成一个”,那就太好了。有没有更优雅的方法可以做到这一点呢

对于代码质量来说,盲选几乎总是一个坏消息,所以它实际上是相当好的 使之难以做到

我会选择接口路径,因为它也会消除用于存储
b
接口{}
。 如果您确实拥有多种类型,并且它们只共享嵌入
a
a接口的特性 它提供了
AVal()A
对我来说很好

作为奖励,您可以直接在
a
上定义
AVal()a
,这样就不需要为嵌入
a
的每种类型实现它

示例():

请注意,我现在使用的是指针值,因此
AVal()*a
不会返回副本,而是
A
的相应实例

如果我能像你在Java中所做的那样“把它转换成一个”,那就太好了。有没有更优雅的方法可以做到这一点呢

对于代码质量来说,盲选几乎总是一个坏消息,所以它实际上是相当好的 使之难以做到

我会选择接口路径,因为它也会消除用于存储
b
接口{}
。 如果您确实拥有多种类型,并且它们只共享嵌入
a
a接口的特性 它提供了
AVal()A
对我来说很好

作为奖励,您可以直接在
a
上定义
AVal()a
,这样就不需要为嵌入
a
的每种类型实现它

示例():

请注意,我现在使用的是指针值,因此
AVal()*a
不会返回副本,而是
A

的相应实例使用
i(B)断言
i
B
。之后,您可以从该断言值请求
A
,因为它是
B
的成员。这里没有魔法。遗憾的是,这要求您测试
i
每种可能的类型,因为
B
可能不是唯一具有
A
的类型。因此此方法可能不是最好的。@nemo-是的,这正是di我遇到的困难。我不想让代码“知道”B,因为B实际上是在使用该包的另一个包中创建的