英文:
How do I initialize a composed struct in Go?
问题
假设我有一个在另一个结构体中嵌入的结构体。
type Base struct {
ID string
}
type Child struct {
Base
a int
b int
}
当我初始化Child
时,我不能直接初始化ID
字段。
// 在类型为Child的结构体字面值中,未知字段'ID'
child := Child{ ID: id, a: a, b: b }
相反,我必须单独初始化ID字段。
child := Child{ a: 23, b: 42 }
child.ID = "foo"
这似乎违反了封装性。Child的使用者必须知道ID字段有所不同。如果我将公共字段移动到嵌入的结构体中,这可能会破坏初始化过程。
我可以为每个结构体编写一个NewFoo()
方法,并希望每个人都使用它,但是***有没有一种安全地使用结构体字面值的方式,而不会暴露一些字段是嵌入的?***或者我在这里应用了错误的模式?
英文:
Let's say I have a struct with another struct embedded in it.
type Base struct {
ID string
}
type Child struct {
Base
a int
b int
}
When I go to initialize Child
, I can't initialize the ID
field directly.
// unknown field 'ID' in struct literal of type Child
child := Child{ ID: id, a: a, b: b }
I instead have to initialize the ID field separately.
child := Child{ a: 23, b: 42 }
child.ID = "foo"
This would seem to violate encapsulation. The user of Child has to know there's something different about the ID field. If I later moved a public field into an embedded struct, that might break initialization.
I could write a NewFoo()
method for every struct and hope everyone uses that, but is there a way to use the struct literal safely with embedded structs that doesn't reveal some of the fields are embedded? Or am I applying the wrong pattern here?
答案1
得分: 54
使用嵌套的复合字面量在单个表达式中初始化一个值:
child := Child{Base: Base{ID: id}, a: a, b: b}
Go issue 9859 提议对复合字面量进行更改,使其与嵌入类型的字段访问保持一致。这个改变将允许使用问题中的 Child{ ID: id, a: a, b: b }
表达式。
嵌入类型并不提供封装,也就是说该特性不会限制对嵌入类型的直接访问。应用程序可以直接访问 child.Base.ID
,同时也可以使用 child.ID
。
英文:
Use nested composite literals to initialize a value in a single expression:
child := Child{Base: Base{ID: id}, a: a, b: b}
Go issue 9859 proposes a change to make composite literals consistent with field access for embedded types. This change will allow the Child{ ID: id, a: a, b: b }
expression from the question.
Embedded types do not provide encapsulation in the sense that the feature does not restrict direct access the embedded type. An application can directly access child.Base.ID
in addition to using child.ID
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论