通过 Go (go 1.18) 泛型创建类型值的新对象
Create new object of typed value via Go (go 1.18) generics
我正在玩 go 1.18 的 beta 版中的泛型。下面示例中的创建函数应该创建 *T
的新实例(因此 *Apple
)。我尝试为此使用反射包,但没有成功。
你能告诉我如何更改下面示例中的函数 Create
以便它创建 T
的实例而不是返回 nil 并使我的示例崩溃吗?
type FruitFactory[T any] struct{}
func (f FruitFactory[T]) Create() *T {
//how to create non-nil fruit here?
return nil
}
type Apple struct {
color string
}
func example() {
appleFactory := FruitFactory[Apple]{}
apple := appleFactory.Create()
//panics because nil pointer access
apple.color = "red"
}
由于您使用非指针类型 (Apple
) 实例化 FruitFactory
,您可以只声明一个类型化变量和 return 它的地址:
func (f FruitFactory[T]) Create() *T {
var a T
return &a
}
或者:
func (f FruitFactory[T]) Create() *T {
return new(T)
}
游乐场:https://gotipplay.golang.org/p/IJErmO1mrJh
如果你想用指针类型实例化 FruitFactory
并且仍然避免分段错误,事情会变得更加复杂。基本上你必须利用类型推断在方法主体中声明一个非指针类型的变量并将其转换为指针类型。
// constraining a type to its pointer type
type Ptr[T any] interface {
*T
}
// the first type param will match pointer types and infer U
type FruitFactory[T Ptr[U], U any] struct{}
func (f FruitFactory[T,U]) Create() T {
// declare var of non-pointer type. this is not nil!
var a U
// address it and convert to pointer type (still not nil)
return T(&a)
}
type Apple struct {
color string
}
func main() {
// instantiating with ptr type
appleFactory := FruitFactory[*Apple, Apple]{}
apple := appleFactory.Create()
// all good
apple.color = "red"
fmt.Println(apple) // &{red}
}
游乐场:https://gotipplay.golang.org/p/07nUGI-xP0O
编辑,2022 年 3 月:已定义类型的类型推断 has been disabled,因此第二个 playground 不再编译。留下原文供参考。您必须提供所有类型参数:FruitFactory[*Apple, Apple]{}
,这确实使它变得非常冗长。类型推断对函数正常工作。
我正在玩 go 1.18 的 beta 版中的泛型。下面示例中的创建函数应该创建 *T
的新实例(因此 *Apple
)。我尝试为此使用反射包,但没有成功。
你能告诉我如何更改下面示例中的函数 Create
以便它创建 T
的实例而不是返回 nil 并使我的示例崩溃吗?
type FruitFactory[T any] struct{}
func (f FruitFactory[T]) Create() *T {
//how to create non-nil fruit here?
return nil
}
type Apple struct {
color string
}
func example() {
appleFactory := FruitFactory[Apple]{}
apple := appleFactory.Create()
//panics because nil pointer access
apple.color = "red"
}
由于您使用非指针类型 (Apple
) 实例化 FruitFactory
,您可以只声明一个类型化变量和 return 它的地址:
func (f FruitFactory[T]) Create() *T {
var a T
return &a
}
或者:
func (f FruitFactory[T]) Create() *T {
return new(T)
}
游乐场:https://gotipplay.golang.org/p/IJErmO1mrJh
如果你想用指针类型实例化 FruitFactory
并且仍然避免分段错误,事情会变得更加复杂。基本上你必须利用类型推断在方法主体中声明一个非指针类型的变量并将其转换为指针类型。
// constraining a type to its pointer type
type Ptr[T any] interface {
*T
}
// the first type param will match pointer types and infer U
type FruitFactory[T Ptr[U], U any] struct{}
func (f FruitFactory[T,U]) Create() T {
// declare var of non-pointer type. this is not nil!
var a U
// address it and convert to pointer type (still not nil)
return T(&a)
}
type Apple struct {
color string
}
func main() {
// instantiating with ptr type
appleFactory := FruitFactory[*Apple, Apple]{}
apple := appleFactory.Create()
// all good
apple.color = "red"
fmt.Println(apple) // &{red}
}
游乐场:https://gotipplay.golang.org/p/07nUGI-xP0O
编辑,2022 年 3 月:已定义类型的类型推断 has been disabled,因此第二个 playground 不再编译。留下原文供参考。您必须提供所有类型参数:FruitFactory[*Apple, Apple]{}
,这确实使它变得非常冗长。类型推断对函数正常工作。