英文:
Why would you want to use composition in golang?
问题
在下面的代码中,我展示了我认为在Go语言中嵌入(其中方法被提升)和组合(其中方法不被提升)之间的区别。
为什么你会想要在Go语言中使用组合?
type obj1Inherited struct {
obj2
}
type obj1Composed struct {
someobj obj2
}
type obj2 struct {
}
func (o obj2) printTest() {
fmt.Println("obj2")
}
func main() {
o := obj1Inherited{}
o.printTest() //fine - printTest is promoted
obj1Composed := obj1Composed{}
obj1Composed.someobj.printTest() //fine because I'm using the composed obj
obj1Composed.printTest() //not fine - printTest is NOT promoted
}
英文:
In the following code I show what I think is the difference between embedding (where methods get promoted) and composition (where methods are not promoted) in golang.
Why would you ever want to use composition in golang?
type obj1Inherited struct {
obj2
}
type obj1Composed struct {
someobj obj2
}
type obj2 struct {
}
func (o obj2) printTest() {
fmt.Println("obj2")
}
func main() {
o := obj1Inherited{}
o.printTest() //fine - printTest is promoted
obj1Composed := obj1Composed{}
obj1Composed.someobj.printTest() //fine because I'm using the composed obj
obj1Composed.printTest() //not fine - printTest is NOT promoted
答案1
得分: 17
在Effective Go中,值得仔细阅读关于嵌入的部分。
一个常见的例子是在结构体/映射中使用互斥锁。
type SafeStruct struct {
SomeField string
*sync.Mutex
}
这样做比编写适当的包装函数(这样做很重复)或者使用 stutter(在这种情况下是 safe.mutex.Unlock()
)要容易得多。
使用嵌入的方式,你只需要这样做:
safe := SafeStruct{SomeField: "init value"}
safe.Lock()
defer safe.Unlock()
safe.SomeField = "new value"
这在你尝试在嵌入字段上使用多个函数(实现了像 io.ReadWriter
这样的接口)时尤其有用。
英文:
It is worth going over the section on Embedding in Effective Go.
A common example is having a struct/map with a Mutex.
type SafeStruct struct {
SomeField string
*sync.Mutex
}
It is much easier to type
safe := SafeStruct{SomeField: "init value"}
safe.Lock()
defer safe.Unlock()
safe.SomeField = "new value"
than having to either write appropriate wrapper functions (which are repetitive) or have the stutter of
safe.mutex.Unlock()
when the only thing you would ever do with the mutex field is access the methods (Lock()
and Unlock()
in this case)
This becomes even more helpful when you are trying to use multiple functions on the embedded field (that implemement an interface like io.ReadWriter
).
答案2
得分: 0
我想再提一点,关于你示例中的第一个情况。
如果obj1Inherited
和obj2
有一个同名的方法,那么从obj1Inherited
实例调用的方法将始终执行obj1Inherited
的方法。
要调用obj2
的方法,你可以使用另一种方法,不要提升...
英文:
One more point I want to cover for first case in your example.
If obj1Inherited
and obj2
have a same name method then that method call (from obj1Inherited
instance) will always execute obj1Inherited
method.
To call obj2
method you can use the other approach of not promoting
答案3
得分: 0
我会尝试回答原始问题 - 有时人们使用"composition"来代替嵌入以隐藏嵌入结构的功能。这不是一个很好的用例,但有时人们更喜欢这样做。
type Obj1composed struct {
notExportedObj1 obj1
}
func NewObj1Composed(someParam Params) Obj1composed {
...
}
func (o Obj1Composed) Print() {
// 这里进行一些繁重的计算。进行数十个API调用
// 打印一些数据
}
英文:
I'll try to answer original question - sometimes people use "composition" instead of embedding to hide functionality of embedded struct. Not a great use case - but people prefer it sometimes.
type Obj1composed struct {
notExportedObj1 obj1
}
func NewObj1Composed(someParam Params) Obj1composed {
...
}
func (o Obj1Composed) Print() {
// Some heavy calculations here. Make Dozens of API calls
// print some data
}
答案4
得分: 0
在Golang中,有3种类型的embed
:
- 在结构体中嵌入结构体
- 在接口中嵌入接口
- 在结构体中嵌入接口
详细信息可以参考这篇文章:https://eli.thegreenplace.net/2020/embedding-in-go-part-1-structs-in-structs/
英文:
In Golang, there are 3 types of embed
- struct embed in struct
- interface embed in interface
- interface embed in struct
In detail you can refer to this post: https://eli.thegreenplace.net/2020/embedding-in-go-part-1-structs-in-structs/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论