亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go函數創建泛型的新指針或新值

Go函數創建泛型的新指針或新值

Go
陪伴而非守候 2022-11-23 10:24:15
我有一個采用泛型類型的函數,應該返回一個始終返回指針的函數。也就是說,如果你傳遞給它一個非指針類型,它應該返回一個指向該類型的指針,如果你傳遞給它一個指針類型,它應該返回相同的類型。我不想使用reflect.New,因為它是一個性能關鍵型應用程序。我不介意在返回工廠函數的函數中使用反射,但理想情況下甚至不在那里。這就是我想要做的:package mainimport (    "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())}
查看完整描述

1 回答

?
阿波羅的戰車

TA貢獻1862條經驗 獲得超6個贊

這種條件類型不能用泛型很好地解決,因為當你用它實例化時T any,*Foo你會丟失關于基類型的信息。事實上,您的代碼仍然使用反射和any(= interface{}),并且makeN函數的返回類型必須被類型斷言為*Foo.


您可以使用當前代碼獲得的最接近的是:


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

    if typ := reflect.TypeOf(v); typ.Kind() == reflect.Ptr {

        elem := typ.Elem()

        return func() any {

            return reflect.New(elem).Interface() // must use reflect

        }

    } else {

        return func() any { return new(T) } // v is not ptr, alloc with new

    }

}

然后兩個 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


查看完整回答
反對 回復 2022-11-23
  • 1 回答
  • 0 關注
  • 150 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號