【问题标题】:generics with a T type and a 'Typed' function that takes T具有 T 类型和采用 T 的 \'Typed\' 函数的泛型
【发布时间】:2023-01-28 04:26:22
【问题描述】:

有一个模块定义了一堆类型

type Thing1 struct {}

type Thing2 struct {}

以及将这些类型作为参数的函数类型

type T1 func(t *Thing1) {...}
type T2 func(t *Thing2) {...}

然后它使用这些函数类型定义一个映射

var (
ModThing1 = map[string] T1
ModThing2 = map[string] T2
)

在我使用此模块的应用程序中,我想对 Thing1 和 Thing2 使用泛型

就像是

func do[T any](in *T, inMap map[string]func(in *T)) {
  for _, val := range inMap {
     val(in)
  }
}
...
do[mod.Thing1](&mod.Thing1{}, mod.ModThing1)

当然问题是 go 不允许这样做,因为映射值的类型与 mod.ModThing1 值类型不同。 'func(in *T))' 与 'mod.T1'

无论如何让这个工作?

【问题讨论】:

    标签: go generics


    【解决方案1】:

    在函数do 中,声明一个额外的类型参数F,其近似约束也引用T。函数参数的类型统一将完成剩下的工作。

    func main() {
        do(&foo.Thing1{}, foo.ModThing1)
        do(&foo.Thing2{}, foo.ModThing2)
    }
    
    func do[T any, F ~func(*T)](in *T, inMap map[string]F) {
        for _, val := range inMap {
            val(in)
        }
    }
    

    游乐场:https://go.dev/play/p/wiWWzXVDG7v


    如果您可以控制导入的包,另一种解决方案是使用通用函数类型而不是 T1T2,假设它们足够相似:

    type F[T any] func(t *T)
    
    // instead of
    // type T1 func(t *Thing1)
    // type T2 func(t *Thing2)
    

    然后你用F[T]的特定实例声明映射变量:

    var (
        ModThing1 = map[string]F[Thing1]{ ... }
        ModThing2 = map[string]F[Thing2]{ ... }
    )
    

    然后在 do 函数中使用类型参数实例化 F

    func do[T any](in *T, inMap map[string]F[T]) {
        for _, val := range inMap {
            val(in)
        }
    }
    

    游乐场:https://go.dev/play/p/ITBqiqjjVUz


    顺便说一句,您还可以抽象地图类型:

    type M[T any] map[string]F[T]
    
    func do[T any](in *T, inMap M[T]) {
        for _, val := range inMap {
            val(in)
        }
    }
    

    【讨论】:

    • 我的问题是 ModThing1 和 ModThing2 是在我不应该编辑的“模块”中定义和填充的(不在我的团队域中)。我可以去要求更改模块,但我想避免这种情况(但我认为这是解决此问题的唯一方法)。
    • @交流。你想做的是可能的,请检查第一个解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    • 2019-03-21
    • 2013-08-29
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多