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

Convert func(T) to 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: cannot use f (variable of type func() T) as type func() any in struct literal

有趣的是,如果我不需要在结构中有一个函数指针,这就可以工作。参见 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...
}

问题已关闭,所以我必须在这里回答问题的第二部分

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

上面的答案是肯定的。

解决方案:

最初我虽然是这样的:“func() 适合 func()any 适合 T 所以为什么我不能有 func() T适合func() any?”当然原因是 func() any 不是 any 所以它不能容纳 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 })
}

but also have several of these structs in a map or slice

您不能这样做(以类型安全的方式)。例如的所有值切片必须具有相同的元素类型。如果你想存储不同的,你必须求助于 interface{} 并稍后输入 switch。

如果你使用正确的技术术语参数多态性而不是“泛型”,它不能解释发生了什么,你就会明白为什么 func(T) 和 func(any) 是不同的、不可转换的类型。

So, is there a way for me to turn a T into an any?

不,没有“泛型”之前的方式,也没有 post-“泛型”方式。将“转换为”视为 Go 允许的内容会有所帮助:“类型转换”和“赋值”。您可以将任何 T 类型的变量分配给任何类型的变量。

您可以通过使用适配器函数(闭包)来解决您的问题:

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