减少 Golang 中的代码重复
Reducing code duplication in Golang
我找不到 "go-way" 来解决代码重复问题。这就是问题所在。考虑以下因素:
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
// ... etc ...
}
FirstType struct { ... }
SecondType struct { ... }
// ... etc ...
)
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
现在,SharedFunctionality
中的方法只依赖于 key()
方法的结果。我可以像下面这样实现它们:
func runMethodA(k WithKey) string {
key := k.key()
// do something and return a string
}
func runMethodB(k WithKey) string {
key := k.key()
// do something else and return a string
}
func (ft *FirstType) MethodA() string { return runMethodA(ft) }
func (ft *FirstType) MethodB() string { return runMethodB(ft) }
func (st *SecondType) MethodA() string { return runMethodA(st) }
func (st *SecondType) MethodB() string { return runMethodB(st) }
我不喜欢这种方法的地方在于,当我添加更多类型(ThirdType、FourthType 等)或向 SharedFunctionality 添加更多方法时,我必须添加大量样板代码...特别是对于 M SharedFunctionality 中的方法和 N 类型,我将不得不像上面的 4 个一样拼出 M*N 个单行代码。
我喜欢做的是:
func (k WithKey) MethodA() string {
key := k.key()
// do something
}
换句话说:我喜欢在接口类型上定义一个方法。含义:所有实现 "WithKey" 的对象将自动获得 MethodA() string
、MethodB() string
等,因此它们将自动实现 SharedFunctionality
接口。 Java接口.
中的默认方法
但是,我知道在接口类型中定义方法是不可能的...
解决这个问题的方法是什么?
我见过一种方法,我会创建一个带有接口类型的匿名字段的结构,然后在其中实现方法:
type SharedFuncStruct struct {
WithKey
}
func (sfs *SharedFuncStruct) MethodA() string {
key := sfs.key()
// whatever
}
// same for MethodB()
然后要使用它,我会做类似的事情:
first := ... getFirstTypeValue()
sfs := &SharedFuncStruct{first}
sfs.MethodA() // etc
这看起来可行,但感觉样板代码太多了。
还有其他选择吗?
在我看来你需要提取一个包。我拥有该功能的方式是
package keyed
type hasKey interface {
Key() string
}
func MethodA(k hasKey) string {
key := k.Key()
// whatever
}
func MethodB(k hasKey) string {
key := k.Key()
// whatever
}
然后
package your_package
import "keyed"
type (
FirstType struct { ... }
SecondType struct { ... }
)
func (ft *FirstType) Key() string { ... }
func (st *SecondType) Key() string { ... }
func main() {
first := &FirstType{}
second := &SecondType{}
keyed.MethodA(first)
keyed.MethodA(second)
keyed.MethodB(first)
keyed.MethodB(second)
}
有趣的事实:您可以将接口嵌入到结构中,然后结构会自动实现该接口。您可以使用它来有效地在接口上定义方法:
https://play.golang.org/p/ZufTOzr9ig
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
}
KeyHolder struct {
WithKey
}
FirstType struct { ... }
SecondType struct { ... }
)
func (k *KeyHolder) MethodA() string {
key := k.key()
// ...
}
func (k *KeyHolder) MethodB() string {
key := k.key()
// ...
}
func NewSharedFunctionality(w WithKey) SharedFunctionality {
return &KeyHolder{w}
}
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
在这种情况下,KeyHolder
结构嵌入了 WithKey
接口,因此可以容纳任何具有 key() string
方法(FirstType
和 SecondType
有)。然后,您可以在该结构上定义 MethodA
和 MethodB
,然后该结构将满足 WithKey
接口(因为它嵌入了它)和 SharedFunctionality
接口,使用任何密钥由嵌入的 WithKey
.
返回
换句话说,不是将 FirstType
包装在 WithKey
中,然后包装在 SharedFunctionality
中(意味着 FirstType
本身必须定义 key()
,MethodA()
,和 MethodB()
),你将 FirstType
包装在 WithKey
中,然后将它嵌入(作为 WithKey
接口)在一些其他结构中,这些结构仅用于定义那些默认值方法 MethodA
和 MethodB
,然后实现 SharedFunctionality
接口。
我找不到 "go-way" 来解决代码重复问题。这就是问题所在。考虑以下因素:
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
// ... etc ...
}
FirstType struct { ... }
SecondType struct { ... }
// ... etc ...
)
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
现在,SharedFunctionality
中的方法只依赖于 key()
方法的结果。我可以像下面这样实现它们:
func runMethodA(k WithKey) string {
key := k.key()
// do something and return a string
}
func runMethodB(k WithKey) string {
key := k.key()
// do something else and return a string
}
func (ft *FirstType) MethodA() string { return runMethodA(ft) }
func (ft *FirstType) MethodB() string { return runMethodB(ft) }
func (st *SecondType) MethodA() string { return runMethodA(st) }
func (st *SecondType) MethodB() string { return runMethodB(st) }
我不喜欢这种方法的地方在于,当我添加更多类型(ThirdType、FourthType 等)或向 SharedFunctionality 添加更多方法时,我必须添加大量样板代码...特别是对于 M SharedFunctionality 中的方法和 N 类型,我将不得不像上面的 4 个一样拼出 M*N 个单行代码。
我喜欢做的是:
func (k WithKey) MethodA() string {
key := k.key()
// do something
}
换句话说:我喜欢在接口类型上定义一个方法。含义:所有实现 "WithKey" 的对象将自动获得 MethodA() string
、MethodB() string
等,因此它们将自动实现 SharedFunctionality
接口。 Java接口.
但是,我知道在接口类型中定义方法是不可能的...
解决这个问题的方法是什么?
我见过一种方法,我会创建一个带有接口类型的匿名字段的结构,然后在其中实现方法:
type SharedFuncStruct struct {
WithKey
}
func (sfs *SharedFuncStruct) MethodA() string {
key := sfs.key()
// whatever
}
// same for MethodB()
然后要使用它,我会做类似的事情:
first := ... getFirstTypeValue()
sfs := &SharedFuncStruct{first}
sfs.MethodA() // etc
这看起来可行,但感觉样板代码太多了。
还有其他选择吗?
在我看来你需要提取一个包。我拥有该功能的方式是
package keyed
type hasKey interface {
Key() string
}
func MethodA(k hasKey) string {
key := k.Key()
// whatever
}
func MethodB(k hasKey) string {
key := k.Key()
// whatever
}
然后
package your_package
import "keyed"
type (
FirstType struct { ... }
SecondType struct { ... }
)
func (ft *FirstType) Key() string { ... }
func (st *SecondType) Key() string { ... }
func main() {
first := &FirstType{}
second := &SecondType{}
keyed.MethodA(first)
keyed.MethodA(second)
keyed.MethodB(first)
keyed.MethodB(second)
}
有趣的事实:您可以将接口嵌入到结构中,然后结构会自动实现该接口。您可以使用它来有效地在接口上定义方法:
https://play.golang.org/p/ZufTOzr9ig
type (
WithKey interface {
key() string
}
SharedFunctionality interface {
WithKey
MethodA() string
MethodB() string
}
KeyHolder struct {
WithKey
}
FirstType struct { ... }
SecondType struct { ... }
)
func (k *KeyHolder) MethodA() string {
key := k.key()
// ...
}
func (k *KeyHolder) MethodB() string {
key := k.key()
// ...
}
func NewSharedFunctionality(w WithKey) SharedFunctionality {
return &KeyHolder{w}
}
func (ft *FirstType) key() string { ... }
func (st *SecondType) key() string { ... }
在这种情况下,KeyHolder
结构嵌入了 WithKey
接口,因此可以容纳任何具有 key() string
方法(FirstType
和 SecondType
有)。然后,您可以在该结构上定义 MethodA
和 MethodB
,然后该结构将满足 WithKey
接口(因为它嵌入了它)和 SharedFunctionality
接口,使用任何密钥由嵌入的 WithKey
.
换句话说,不是将 FirstType
包装在 WithKey
中,然后包装在 SharedFunctionality
中(意味着 FirstType
本身必须定义 key()
,MethodA()
,和 MethodB()
),你将 FirstType
包装在 WithKey
中,然后将它嵌入(作为 WithKey
接口)在一些其他结构中,这些结构仅用于定义那些默认值方法 MethodA
和 MethodB
,然后实现 SharedFunctionality
接口。