Struct 通过值或指针访问另一个结构
通过值或指针访问另一个结构时有什么区别?Struct 通过值或指针访问另一个结构,struct,pointers,go,Struct,Pointers,Go,通过值或指针访问另一个结构时有什么区别? 什么时候应该使用它们中的每一个 type foo_ struct { st uint8 nd uint8 } type bar struct { rd uint8 foo foo_ } type barP struct { rd uint8 foo *foo_ } 答案在很大程度上与语言无关——C语言中的等价物也有同样的问题 当您有一个嵌入值(如bar)时,您的结构就足够大,可以容纳完整的子结构和
什么时候应该使用它们中的每一个
type foo_ struct {
st uint8
nd uint8
}
type bar struct {
rd uint8
foo foo_
}
type barP struct {
rd uint8
foo *foo_
}
答案在很大程度上与语言无关——C语言中的等价物也有同样的问题 当您有一个嵌入值(如
bar
)时,您的结构就足够大,可以容纳完整的子结构和其他部分
当您有一个指向某个值的指针(如barP
)时,许多类型为barP
的结构可能共享相同的foo
。当任何barP
修改它指向的foo
的一部分时,它会影响指向同一位置的所有其他barP
结构。此外,正如注释所示,您必须管理两个单独的对象,barP
和foo
,而不是普通的bar
类型
在某些语言中,您必须担心指针悬空和未初始化的值等问题;Go是垃圾收集的,通常比其他语言更安全
因此,当您希望多个
barP
对象共享同一foo
对象时,请使用指针;否则,请使用显式成员对象,而不是指向对象的指针。如果声明或分配了类型bar
的变量,则为rd uint8
和foo foo
保留并初始化为零内存。始终有一个类型foo\ucode>的变量嵌入到类型bar
的变量中
var b bar // declare b
如果您声明或分配一个barP类型的变量
,则为rd uint8
和foo*foo
保留并初始化为零内存。零值指针是nil
指针。未分配类型为foo\u0的变量;你必须分开做。有零(foo==nil
)或一个类型foo的变量被类型barP
的变量指向。类型barP
的变量可能指向与类型barP
的其他变量相同的类型foo
变量,共享类型foo
变量的相同副本。指向共享副本的所有变量都可以看到对共享副本的更改
var bp barP // declare bp
bp.foo = new(foo_) // allocate bp.foo
使用哪一种取决于类型bar
与类型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
}
现在,本节总结了以下内容之间的区别:
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
首先,也是最重要的一点,该方法是否需要修改接收器?
如果是,则接收器必须是指针。(切片和贴图都是引用类型,因此它们的故事要微妙一些,但例如,要在方法中更改切片的长度,接收者仍然必须是指针。)
在上面的示例中,如果pointerMethod
修改s
的字段,调用方将看到这些更改,但是调用方的参数副本调用了valueMethod
(这是传递值的定义),因此调用方将看不到它所做的更改。
顺便说一句,指针接收器与Java中的情况完全相同,尽管在Java中指针隐藏在盖子下面;Go的价值接受者与众不同
第二是对效率的考虑。如果接收器很大,例如一个大结构,那么使用指针接收器会便宜得多
(该效率点也在“”中说明)
接下来是一致性。如果该类型的某些方法必须具有指针接收器,那么其他方法也应该具有指针接收器,这样无论该类型如何使用,方法集都是一致的。有关详细信息,请参阅上的部分
当声明或分配barP
类型的变量时,foo的初始值将是nil
指针。