php小編草莓在這篇文章中將向大家介紹如何取得不帶型別參數的泛型結構的型別名稱。泛型是一種強大的程式設計技術,可以在不指定具體類型的情況下編寫通用的程式碼。然而,有時我們可能需要取得泛型結構的型別名稱,而不包含特定的型別參數。本文將為您詳細解答這個問題,幫助您更能理解並應用泛型程式設計。
假設我有一個名為 foo
的通用結構,我從中建立了兩個物件。我可以使用 reflect.typeof()
確定每個的具體類型,如下所示:
package main import ( "fmt" "reflect" ) type foo[t any] struct { data t } func main() { a := foo[string]{"cheese"} b := foo[int]{42} fmt.println(reflect.typeof(a)) fmt.println(reflect.typeof(b)) } // main.foo[string] // main.foo[int]
我感興趣的是確定這些物件的通用類型(即foo
),而不是具體類型(即foo[string]
和foo[int]
)。這是可能的還是我需要手動從這些字串中提取通用類型(例如,使用正規表示式)?
正規表示式可能看起來像這樣:
func GetGenericType(x any) string { // Get type as a string s := reflect.TypeOf(x).String() // Regex to run r := regexp.MustCompile(`\.(.*)\[`) // Return capture return r.FindStringSubmatch(s)[1] } fmt.Println(GetGenericType(a)) fmt.Println(GetGenericType(b)) // foo // foo
我也看到了這個問題,但這並沒有回答這個問題,因為它給了具體類型(即main.foo[string]
)而不是通用類型(即, foo
)。
反射看不到「基本」泛型類型的名稱,因為在運行時該基本類型不存在。
go 規範中的相關段落是 實例化:
實例化一個類型會產生一個新的非泛型命名類型;實例化一個函數會產生一個新的非泛型函數。
所以當你寫:
b := foo[int]{42} name := reflect.typeof(b).name()
該類型的名稱正是 foo[int]
。
值得注意的是,不含類型參數清單的標識符 foo
在編譯時是相關的,因為它可以防止您在同一個套件中重新聲明它。 類型定義:
類型定義建立一個新的、不同的類型,具有相同的類型 底層類型和操作作為給定類型並綁定 標識符,類型名稱,給它。
typedef = identifier [ typeparameters ] type .
但是,如上所述,實例化會產生一個與 foo
不同的新命名類型;在執行時,當您可以使用反射時,您只處理實例化。
總之,我認為你的正規表示式解決方案是可以接受的,直到一些輔助函數被添加到stdlib中(如果有的話) 。為了清楚起見,將其重新發佈到此處:
func getgenerictype(x any) string { // get type as a string s := reflect.typeof(x).string() // regex to run r := regexp.mustcompile(`\.(.*)\[`) // return capture return r.findstringsubmatch(s)[1] }
請記住type.string()
和type.name()
之間的差異:任何型別都可以有字串表示形式,但只有命名型別才有名稱。 (顯然,對吧?)。例如,如果您寫道:
b := &foo[int]{42}
那麼b
的類型為*foo[int]
,為匿名複合類型,name()
傳回空字串。
以上是取得不帶型別參數的泛型結構的型別名稱的詳細內容。更多資訊請關注PHP中文網其他相關文章!