使用struct成员作为另一个struct中的成员

时间:2015-04-13 05:00:33

标签: go struct embedding

type (
    A struct {
        a string
    }

    B struct {
        b *A.a
    }
)

我收到此错误:

A.a undefined (type A has no method a)

我在这里遗漏了什么吗?或者Go中不允许这样做?

2 个答案:

答案 0 :(得分:4)

定义结构字段时,必须像使用struct A.a一样指定its name and its type。但是在结构B中:

b *A.a

*A.a不是一种类型。

您无法在另一个结构中嵌入struct的字段。请注意,您可以通过省略 name 部分将完整结构嵌入到另一个结构中:

type (
    A struct {
        a string
    }

    B struct {
        A
    }
)

结果是A类型的所有字段和方法也将成为struct B的成员。如果您需要A的嵌入式结构B,可以通过将其作为类型名称来访问它:

var b B
fmt.Println(b.A)

您可以做的另一件事是在B中有一个字段,它是一个指针,它指向A类型的现有值的字段:

B struct {
    ap *string
}

a := A{a:"test"}
b := B{ap:&a.a} // B.ap will point to a.a

fmt.Println(*b.ap) // Prints "test"

答案 1 :(得分:0)

问题是您使用*A.a作为字段b的类型说明符。你唯一缺少的是你应该有b stringb *string(如果你想在结构B中至少有一个字符串字段)。

现在,如果您的目标是做更多像继承'然后,您应该在A嵌入 B,这将为B提供名为a的属性。这看起来像这样;

type B struct {
      A
}

这是继承Go提供的最相似的构造。如果你要嵌入这里,你就可以做类似的事情。

var instanceOfB = &B{}
fmt.Println(instanceOfB.a)

这在功能上等同于B从A继承(在这种情况下,两个事情虽然不同但行为在很多方面都不同。我认为它有助于比较/对比继承)。此时,您可以直接从A的实例访问B上的属性或方法。尽管它们不会导致编译器错误,但最好避免名称冲突。如果您确实在嵌入类型或嵌入式类型与嵌入式类型之间存在命名冲突,则决定在运行时使用哪个方法/属性,并且我不确定解析规则是什么,但我认为您可以在语言规范。

现在我的最后一个想法......如果您的目标是从a的某个实例引用A实例中的B属性,您只想包含一个刺痛指针在B中,并在实例化&A.a时将构造函数中的B设置为静态初始值设定项。然而,这可能是一种不好的做法,因为它违背了封装的概念,而且非常明显容易出错。