泛型:约束具有返回自身的函数的类型
generics: constraint to a type with a function returning itself
是否可以编写泛型类型约束,以便该类型包含返回相同类型的函数,或者它是否与普通接口存在相同的问题?示例用例是具有可链接方法的构建器。
假设我有一个构建器 IntFoo
,它有一个 SetFoo
方法负责将 foo
字段设置为某个值。 Playground link
type IntFoo struct {
foo int
}
func (me *IntFoo) SetFoo(foo int) *IntFoo {
me.foo = foo
return me
}
现在我可能有几个像这个不同类型的构建器,我想定义一个这样的约束:
type Builder[F any] interface {
SetFoo(F) Builder[F] // this return type is problematic
}
和一些使用 Builder 约束类型的函数,如下所示:
// some generic demo function
func demo[E Builder[F], F any](builder E, foo F) {
builder.SetFoo(foo)
return
}
正在尝试调用演示函数
e := &IntFoo{}
demo(e, 2)
导致错误:
[compiler InvalidTypeArg] [E] *IntFoo does not implement Builder[int] (wrong type for method SetFoo)
have SetFoo(foo int) *IntFoo
want SetFoo(int) Builder[int]
您想 return 原始类型 E
- 而不是 Builder
接口 - 来自您的方法:
type Builder[F, E any] interface {
SetFoo(F) E
}
然后重新处理 demo
,因此所需的类型 E
被中继到 Builder
类型约束:
func demo[E Builder[F, E], F any](bldr E, foo F) E {
return bldr.SetFoo(foo)
}
https://go.dev/play/p/2K4D_nzMwU2
v := demo(e, 2)
fmt.Printf("%[1]T : %+[1]v\n", v) // *main.IntFoo : &{foo:2}
是否可以编写泛型类型约束,以便该类型包含返回相同类型的函数,或者它是否与普通接口存在相同的问题?示例用例是具有可链接方法的构建器。
假设我有一个构建器 IntFoo
,它有一个 SetFoo
方法负责将 foo
字段设置为某个值。 Playground link
type IntFoo struct {
foo int
}
func (me *IntFoo) SetFoo(foo int) *IntFoo {
me.foo = foo
return me
}
现在我可能有几个像这个不同类型的构建器,我想定义一个这样的约束:
type Builder[F any] interface {
SetFoo(F) Builder[F] // this return type is problematic
}
和一些使用 Builder 约束类型的函数,如下所示:
// some generic demo function
func demo[E Builder[F], F any](builder E, foo F) {
builder.SetFoo(foo)
return
}
正在尝试调用演示函数
e := &IntFoo{}
demo(e, 2)
导致错误:
[compiler InvalidTypeArg] [E] *IntFoo does not implement Builder[int] (wrong type for method SetFoo)
have SetFoo(foo int) *IntFoo
want SetFoo(int) Builder[int]
您想 return 原始类型 E
- 而不是 Builder
接口 - 来自您的方法:
type Builder[F, E any] interface {
SetFoo(F) E
}
然后重新处理 demo
,因此所需的类型 E
被中继到 Builder
类型约束:
func demo[E Builder[F, E], F any](bldr E, foo F) E {
return bldr.SetFoo(foo)
}
https://go.dev/play/p/2K4D_nzMwU2
v := demo(e, 2)
fmt.Printf("%[1]T : %+[1]v\n", v) // *main.IntFoo : &{foo:2}