通过值或指针访问另一个结构

时间:2010-05-02 18:26:03

标签: struct pointers go

当您通过值或指针访问另一个结构时有什么区别? 什么时候应该使用它们?

type foo_ struct {
    st uint8
    nd uint8
}

type bar struct {
    rd  uint8
    foo foo_
}

type barP struct {
    rd  uint8
    foo *foo_
}

2 个答案:

答案 0 :(得分:5)

如果您声明或分配type bar变量,则为rd uint8foo foo_保留并初始化为零内存。 type foo_变量中始终存在type bar的一个变量。

var b bar  // declare b

如果您声明或分配type barP变量,则为rd uint8foo *foo_保留并初始化为零内存。零值指针是nil指针。没有分配type foo_的变量;你必须分开做。变量foo == nil指向零(type foo_)或type barP的一个变量。变量type barP可能指向与type foo_的其他变量相同的type barP变量,共享type foo_变量的相同副本。所有指向它的变量都会看到对共享副本的更改。

var bp barP         // declare bp
bp.foo = new(foo_)  // allocate bp.foo

使用哪一项取决于type bartype barP的属性。哪种类型更能反映出您试图解决的问题?

例如,请考虑此发票问题。我们总是有账单地址;我们总是要求我们的钱。但是,我们经常发送到帐单邮寄地址,但并非总是如此。如果送货地址为nil,请使用帐单邮寄地址。否则,请使用单独的送货地址。我们有两个仓库,我们总是从一个或另一个出货。我们可以共享两个仓库位置。由于我们在订单从仓库发货之前不发送发票,因此仓库位置永远不会是nil

type address struct {
    street string
    city   string
}

type warehouse struct {
    address string
}

type invoice struct {
    name      string
    billing   address
    shipping  *address
    warehouse *warehouse
}

答案 1 :(得分:2)

答案很大程度上与语言无关 - C语言中的等价物具有相同的问题。

当你有一个嵌入值(如在bar中)时,你的结构就足以容纳完整的子结构和另一部分。

当你有一个指向某个值的指针时(如barP所示),那么barP类型的多个结构可能共享相同的foo。当barP中的任何一个修改了它所指向的foo的一部分时,它会影响指向同一位置的所有其他barP结构。此外,正如评论所建议的那样,您必须管理两个单独的对象 - barPfoo,而不是普通bar类型的对象。

在某些语言中,你不得不担心悬挂指针和未初始化的值等; Go是垃圾收集的,通常比其他语言更安全。

因此,当您希望多个barP个对象共享同一个foo对象时,请使用指针;否则,使用显式成员对象,而不是指向对象的指针。