猿问

Go函数创建泛型的新指针或新值

我有一个采用泛型类型的函数,应该返回一个始终返回指针的函数。也就是说,如果你传递给它一个非指针类型,它应该返回一个指向该类型的指针,如果你传递给它一个指针类型,它应该返回相同的类型。我不想使用reflect.New,因为它是一个性能关键型应用程序。


我不介意在返回工厂函数的函数中使用反射,但理想情况下甚至不在那里。


这就是我想要做的:


package main


import (

    "fmt"

    "reflect"

)


type Ptr[T any] interface {

    *T

}


func makeNewA[T Ptr[U], U any]() any {

    return new(U)

}


func makeNewB[T any]() any {

    return new(T)

}


func makeNew[T any](v T) func() any {

    if reflect.TypeOf(v).Kind() == reflect.Ptr {

        return makeNewA[T] // <-- error: T does not match *U

    } else {

        return makeNewB[T]

    }

}


type Foo struct{}


func main() {

    make1 := makeNew(Foo{})

    make2 := makeNew(&Foo{})


    // should both return &Foo{}

    fmt.Println(make1())

    fmt.Println(make2())

}


陪伴而非守候
浏览 164回答 1
1回答

阿波罗的战车

这种条件类型不能用泛型很好地解决,因为当你用它实例化时T any,*Foo你会丢失关于基类型的信息。事实上,您的代码仍然使用反射和any(= interface{}),并且makeN函数的返回类型必须被类型断言为*Foo.您可以使用当前代码获得的最接近的是:func makeNew[T any](v T) func() any {&nbsp; &nbsp; if typ := reflect.TypeOf(v); typ.Kind() == reflect.Ptr {&nbsp; &nbsp; &nbsp; &nbsp; elem := typ.Elem()&nbsp; &nbsp; &nbsp; &nbsp; return func() any {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return reflect.New(elem).Interface() // must use reflect&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; return func() any { return new(T) } // v is not ptr, alloc with new&nbsp; &nbsp; }}然后两个 maker 函数将返回一个any包装非 nil*Foo值的:fmt.Printf("%T, %v\n", make1(), make1()) // *main.Foo, &{}fmt.Printf("%T, %v\n", make2(), make2()) // *main.Foo, &{}游乐场:https ://gotipplay.golang.org/p/kVUM-qVLLHG进一步的考虑:return makeNewA[T]在您的第一次尝试中不起作用,因为条件reflect.TypeOf(v).Kind() == reflect.Ptr是在运行时评估的,而实例化makeNewA发生在编译时。在编译时T仅受约束any并且any(= interface{}) 未实现Ptr[U]您无法仅使用参数捕获有关指针类型和基类型的信息v。例如makeNew[T Ptr[U], U any](v T),调用 with 时不会编译,调用 with时makeNew(Foo{})将makeNew[T Ptr[U], U any](v U)推断T为**Foo*Foo
随时随地看视频慕课网APP

相关分类

Go
我要回答