我对指针类型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
}
答案 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
指向的内容(如果它是一个值,那么它将始终引用相同的“值”)