通过 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]{},这确实使它变得非常冗长。类型推断对函数正常工作。