将struct vs指针嵌入到用作指针的struct中

时间:2019-07-27 23:35:01

标签: go struct

如果我有一个用作指针的结构类型A(仅具有指针接收器,则构造函数返回*A等),嵌入结构类型{{ 1}}是BB相对?

也就是说,两者之间有什么区别

*B

type B struct {...}
type A struct {
    B
    // ...
}

例如,是否曾经复制过嵌入字段?

编辑:我还应该提到嵌入式结构type B struct {...} type A struct { *B // ... } 仅具有指针接收器。

2 个答案:

答案 0 :(得分:2)

两个结构的零值不同,这可能是人体工程学上的显着差异。

考虑嵌入式类型

type B struct {
    X int
}

func (b *B) Print() { fmt.Printf("%d\n", b.X) }

如果我们直接将其作为对象嵌入

type AObj struct {
    B
}

然后,类型AObj的零值包括类型B的嵌入式对象,该对象也具有其零值,因此我们可以安全地

var aObj AObj
aObj.Print() // prints 0

但是如果我们改为嵌入一个指针

type APtr struct {
    *B
}

该结构的零值具有nil指针值,我们不能真正直接使用它。

var aPtr APtr
aPtr.Print() // panics

希望以您期望的方式复制对象。如果创建一个新的AObj对象,它将获得嵌入式B的副本。

aObj2 := aObj
aObj.X = 1
aObj2.Print() // prints 0, because it has a copy

如果创建一个新的APtr对象,它将获得*B的副本,这意味着它共享基​​础的具体对象。

aPtr.B = &B{}
aPtr2 := aPtr
aPtr.X = 1
aPtr2.Print() // prints 1, because both objects point at the same B

https://play.golang.org/p/XmOgegwVFeE上的可运行示例

答案 1 :(得分:1)

考虑一个简单的示例程序。 structAPtr嵌入指针,structAVal直接嵌入结构structB

package main

import "fmt"

type structB struct {
    foo int
}

type structAPtr struct {
    bar *structB
}

type structAVal struct {
    bar structB
}

func main() {
    // referencing bStruct
    b1 := structB{foo: 12}

    aPtr := structAPtr{bar: &b1}
    fmt.Println("Before assignment:")
    fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)

    aPtr.bar.foo = 42
    fmt.Println("After assignment:")
    fmt.Printf("aPtr.bar.foo = %d, b.foo = %d\n", aPtr.bar.foo, b1.foo)

    // copying bStruct
    b2 := structB{foo: 12}

    aVal := structAVal{bar: b2}
    fmt.Println("Before assignment:")
    fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)

    aVal.bar.foo = 42
    fmt.Println("After assignment:")
    fmt.Printf("aVal.bar.foo = %d, b.foo = %d\n", aVal.bar.foo, b2.foo)
}

int structB.foo用于演示structBstructAPtrstructAVal内部进行操作时是否发生了变化。

该程序输出:

Before assignment:
aPtr.bar.foo = 12, b.foo = 12
After assignment:
aPtr.bar.foo = 42, b.foo = 42 <------------ both changed
Before assignment:
aVal.bar.foo = 12, b.foo = 12
After assignment:
aVal.bar.foo = 42, b.foo = 12 <------------ only assignee changed

查看结果显示:

  • pointer 的值更改为structB会更改structB

  • structB中更改复制版本structAVal的值使structB不受影响(即使分配了5之后,它仍然42aVal


编辑:

如果您的structB仅具有指针接收器,则预期的行为可能是更改structB中的strucA会同时更新它们。在我的示例中,这是场景1,肯定需要一个指针。来自围棋之旅

  

带有指针接收器的方法可以修改接收器指向的值。由于方法通常需要修改其接收者,因此指针接收者比值接收者更为普遍。


希望有帮助!