为了账号安全,请及时绑定邮箱和手机立即绑定

在用作指针的结构中嵌入结构与指向结构的指针

在用作指针的结构中嵌入结构与指向结构的指针

Go
当年话下 2023-07-10 10:49:13
如果我有一个A用作指针的结构类型(仅具有指针接收器,构造函数返回*A等),那么嵌入结构类型与嵌入结构类型有B什么B区别*B?也就是说,有什么区别type B struct {...}type A struct {    B    // ...}和type B struct {...}type A struct {    *B    // ...}例如,是否存在嵌入字段的复制?编辑:我还应该提到嵌入式结构B只有指针接收器。
查看完整描述

2 回答

?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

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


考虑嵌入类型


type B struct {

    X int

}


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

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


type AObj struct {

    B

}

那么 type 的零值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


查看完整回答
反对 回复 2023-07-10
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

考虑一个简单的示例程序。AstructAPtr嵌入一个指针,a直接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)

}

intstructB.foo用于演示在orstructB内部进行操作时是否会发生变化。structAPtrstructAVal


该程序输出:


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

查看结果显示:

  • 改变指针的值来structB改变structB

  • 更改复制版本structB的值不受影响(它仍然是,即使在被分配给之后)structAValstructB542aVal


编辑:

无论如何,如果您structB只有指针接收器,则预期的行为可能是更改structB更新strucA的两个接收器。这是我的示例中的场景 1,并且肯定需要一个指针。来自围棋之旅

具有指针接收器的方法可以修改接收器指向的值[...]。由于方法通常需要修改其接收器,因此指针接收器比值接收器更常见。


查看完整回答
反对 回复 2023-07-10
  • 2 回答
  • 0 关注
  • 177 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信