Golang中是否应该使用指针嵌入?
Golang中是否应该使用指针嵌入?
如下所示,Container 结构体有两个非指针嵌入字段:A 和 []B。它可能包含大量数据。
如果我修改代码,将 *Container 传递给 do() 函数,这将避免重新复制,因此应用程序应该更节省内存。然而,我想理解的是,我是否也应该将嵌入字段 A 和 []B 改为 *A 和 []*B 以避免复制?或者当传递 *Container 时,它们是否已经被复制了?
谢谢
package main
type Container struct {
ID int
// ... 更多字段
A A // 还是 *A?
B []B // 还是 []*B?
}
type A struct {
ID int
// ... 更多字段
}
type B struct {
ID int
// ... 更多字段
}
func main() {
c := Container{
ID: 1,
A: A{
ID: 491,
},
B: []B{
{
ID: 87,
},
},
}
do(c)
}
func do(c Container) {
// 对 `c` 进行一些操作,但不需要修改。
}
更多关于Golang中是否应该使用指针嵌入?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
您无需将字段 A 和 []B 更改为指针类型来避免内存复制。当您将 *Container 传递给 do() 函数时,传递给函数的是 Container 对象的地址。
更多关于Golang中是否应该使用指针嵌入?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中,当传递*Container给函数时,只会复制指针本身(通常为8字节),而不是整个结构体。然而,结构体内部的嵌入字段是否会被复制取决于它们的类型。
对于你的代码示例:
package main
type Container struct {
ID int
A A // 值类型 - 会被完整复制
B []B // slice - 复制slice头(指针+长度+容量)
}
type A struct {
ID int
// ... 更多字段
}
type B struct {
ID int
// ... 更多字段
}
func doByValue(c Container) {
// c.A 被完整复制
// c.B 复制了slice头,但底层数组共享
}
func doByPointer(c *Container) {
// 只复制了指针(8字节)
// 访问c.A和c.B时直接操作原结构体
}
func main() {
c := Container{
ID: 1,
A: A{ID: 491},
B: []B{{ID: 87}},
}
// 值传递 - 复制整个Container
doByValue(c)
// 指针传递 - 只复制指针
doByPointer(&c)
}
关键点:
- 传递
*Container时:只复制指针,不会复制A字段或Bslice的底层数据 A字段(值类型):在Container内部,无论是否使用指针传递Container,A都作为值存储B字段(slice):slice是引用类型,包含指向底层数组的指针
是否需要改为指针嵌入取决于:
// 如果A很大且频繁复制,使用指针
type Container struct {
A *A
B []*B // 如果B元素很大且需要避免复制
}
// 示例:使用指针嵌入
func main() {
c := &Container{
ID: 1,
A: &A{ID: 491},
B: []*B{{ID: 87}},
}
do(c)
}
func do(c *Container) {
// 直接操作原数据,无复制
_ = c.A.ID
_ = c.B[0].ID
}
性能考虑:
- 小结构体(<指针大小):使用值类型
- 大结构体或需要共享状态:使用指针
- slice本身已包含指针,但元素如果是大结构体,考虑
[]*B
内存布局示例:
// 值嵌入:A的数据直接存储在Container内存中
container := Container{A: A{data...}}
// 指针嵌入:Container存储指针,A的数据在堆上
container := Container{A: &A{data...}}
在只读场景且传递*Container的情况下,当前设计已避免大部分复制。是否需要进一步优化取决于A和B的实际大小和使用模式。

