具有公共字段的结构...
type Definition struct {
Id string
...
}
type Requirement struct {
Id string
...
}
type Campaign struct {
Id string
...
}
......我有多种功能,比如:
func fillDefinitionIds(values *map[string]Definition) {
for key, value:=range *values { // Repeated code
value.Id=key // Repeated code
(*values)[key]=value // Repeated code
} // Repeated code
}
func fillRequirementIds(values *map[string]Requirement) {
for key, value:=range *values { // Repeated code
value.Id=key // Repeated code
(*values)[key]=value // Repeated code
} // Repeated code
}
func fillCampaignIds(values *map[string]Campaign) {
for key, value:=range *values { // Repeated code
value.Id=key // Repeated code
(*values)[key]=value // Repeated code
} // Repeated code
}
我希望有一个单一的函数,用泛型(或接口,无论什么)来概括访问,有点...
func fillIds[T Definition|Requirement|Campaign](values *map[string]T) {
for key, value:=range *values {
value.Id=key
(*values)[key]=value
}
}
当然,这会产生value.Id undefined (type T has no field or method Id)
,我已经多次克服了类似的问题,但这次我找不到解决这个问题的方法。
如何将这组函数抽象为单个函数?
3条答案
按热度按时间jtjikinw1#
使用包含公共字段的结构来构建结构,并在该公共类型上定义setter方法:
然后将接口约束定义为指针类型的并集 *,并指定setter方法 *,因为泛型字段访问在当前版本的Go语言中是不可用的。
示例:https://go.dev/play/p/fJhyhazyeyc
lymnna712#
泛型适用于相同代码适用于任意数量的类型的情况,例如:
如果你想用泛型来实际修改不同类型的特定字段,那么泛型就不是一个好方法,这也不是它们的本意,而golang已经有了一些特性来让你做到这一点:组成和接口。
您已经标识了共享字段,非常好,因此创建一个类型并将其嵌入到需要的位置:
现在,在通用类型上添加setter:
现在,所有嵌入
Common
的类型都有一个ID
字段和一个setter:要接受允许您设置ID的所有类型的Map,您真正需要做的只是使
fillIds
接受所需的接口:因为setter根据定义应该是指针接收器,所以你可以把同样的函数写得更短:
使用接口表示这个函数想要通过一个已知的/定义的接口与你传递给它的对象交互。使用泛型表示你期望提供将作为一个整体使用的数据。设置字段并不是将数据作为一个整体使用,因此我认为泛型不是这项工作的正确工具。泛型 * 可以 * 非常强大,在某些情况下非常有用。不久前,我在代码回顾上发表了一篇关于泛型创建并发安全Map的评论,这是一个很好的泛型用例,以至于我最终实现了这样一个类型作为回应,并将其放在github上
我想我应该提到这一点,我一点也不反对泛型。它们可能非常有用。我反对的是过度使用这个特性,这可能--而且经常--导致代码发臭,更难阅读/维护。
db2dz4w83#
https://go.dev/play/p/F3Qk0gcyKEa
如果要求使用 * 值 * 的Map,则@blackgreen答案的替代方案。
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
https://go.dev/play/p/AG050b0peFw