将 func(T) 转换为 func(any)

我希望能够在结构的两个字段之间强制执行相似性,但在映射或切片中也有几个这样的结构。


这是我的问题的一个简化示例:


package main


type foo[T any] struct {

    f func() T

    v T

}


type bar struct {

    x []*foo[any]

}


func baz[T any](b *bar, f func() T) {

    b.x = append(b.x, &foo[any]{f: f})

}


func main() {

    var b bar

    baz(&b, func() int { return 0 })

}

编译器抱怨


./prog.go:13:33: 不能在结构文字中使用 f(func() T 类型的变量)作为 func() any 类型


有趣的是,如果我不需要在结构中有一个函数指针,这就可以工作。请参阅https://go.dev/play/p/qXTmaa9PuVe


那么,有没有办法让我把 T 变成 any?


我知道我可以使用 interface{} 来做到这一点并使用 reflect 来执行我想要的,但我确信只有泛型才有可能。


如果有办法解决我的问题,上下文是我正在制作一个标志包。重要的结构如下所示:


type flag[T any] struct {

    value T

    parse func(in string) (T, error)

    // Other fields removed for simplicity...

}


type FlagSet struct {

    // could flag[any] be replaced with a better answer?

    flags map[string]*flag[any]

    // Other fields removed for simplicity...

}

这个问题已经结束,所以我必须在这里回答我问题的第二部分


可以用更好的答案替换 flag[any] 吗?


上面的答案是肯定的。


解决方案:


最初我虽然是这样的:“一个func()适合一个func(),一个any适合一个T,所以为什么我不能有一个func() T适合的func() any?” 当然原因是 afunc() any不是 anany所以它不能容纳 a func() T。


相反,您可以执行以下操作:


package main


type foo[T any] struct {

    f func() T

    v T

}


func (f *foo[_]) set() {

    f.v = f.f()

}


type anyfoo interface {

    set()

}


type bar struct {

    x []anyfoo

}


func baz[T any](b *bar, f func() T) {

    b.x = append(b.x, &foo[T]{f: f})

}


func main() {

    var b bar

    baz(&b, func() int { return 0 })

}


梦里花落0921
浏览 90回答 1
1回答

慕后森

但在 map 或 slice 中也有几个这样的结构您不能这样做(以类型安全的方式)。例如切片的所有值必须具有相同的元素类型。如果你想存储不同的,你必须求助于interface{}稍后键入 switch。如果您使用正确的技术术语参数多态性而不是不能解释发生了什么的“泛型”,您就会明白为什么 func(T) 和 func(any) 是不同的、不可转换的类型。那么,有没有办法让我把 T 变成 any?不,没有“泛型”之前的方式,也没有“泛型”之后的方式。将“转换为”视为 Go 允许的内容会有所帮助:“类型转换”和“赋值”。您可以将 T 类型的任何变量分配给 any 类型的变量。您可以通过使用适配器函数(闭包)来解决您的问题:w := func(a any){ f(a.(T)) } b.x = append(b.x, &foo[any]{w})
打开App,查看更多内容
随时随地看视频慕课网APP