包装的结构引用

时间:2018-07-06 17:02:40

标签: go struct reference

我对指针类型struct包裹​​的值类型struct感到困惑。

示例:

package main

import (
    "fmt"
)

type A struct {
  id int
  B
}

func (a *A) setId(val int) {
  a.id = val
}

type B struct {
  name string
}

func (b B) setNameViaValue(val string) {
  b.name = val
}

func (b *B) setNameViaPointer(val string) {
  b.name = val
}

func main() {
    a := new(A)
    a.setId(1)
    a.setNameViaValue("valuename")
    fmt.Println(a)
    a.setNameViaPointer("pointername")
    fmt.Println(a)
}

我希望无论使用哪种类型的B引用(B / * B),通过包装B值类型struct的指针类型A struct(用于寻址具体内存)的引用都将设置内部值。这也与类型定义有关。当我这样定义时,谁能解释一下有什么不同?有用例场景吗?

type A struct {
  id int
  *B
}

1 个答案:

答案 0 :(得分:1)

为什么setNameViaValue不设置名称

如果您声明一个带有值(非指针)接收方的方法,则该方法将无法“修改”接收方,因为它实际上将收到一个副本。

这就是为什么未使用setNameViaValue方法设置“名称”的原因。

如果您希望以此方式设置B的名称,则只能选择setNameViaPointer

您可以在此处详细了解方法接收器和值接收器之间的区别:

https://tour.golang.org/methods/8

您为什么实际上可以在外部结构上调用内部结构方法

那是因为您将内部结构“嵌入”在外部结构中。

当您在不提供结构名称的情况下包含结构类型名称时,所有“内部”结构方法和字段都将“提升”为外部结构。

这意味着您可以致电a.setNameViaValue,这等效于进行a.B.setNameViaValue

如果我将其嵌入为指针,有什么区别

如果您以此方式定义A

type A struct {
  id int
  *B
}

然后:

  • “ setNameViaValue”仍将不起作用(这仅与通过值而非指针接收器定义的方法有关,它与A引用B的方式无关)。

  • 在创建A对象时,需要显式初始化B,否则*B最终将为nil。 (如果您将其引用为值,则会将其初始化为空的B

  • 您以后可以更改*B指向的内容(如果它是一个值,那么它将始终引用相同的“值”)