Go語言reflect.TypeOf()和reflect.Type通過反射獲取類型信息
在 Go語言中通過調用 reflect.TypeOf 函數,我們可以從一個任何非接口類型的值創建一個 reflect.Type 值。reflect.Type 值表示著此非接口值的類型。通過此值,我們可以得到很多此非接口類型的信息。當然,我們也可以將一個接口值傳遞給一個 reflect.TypeOf 函數調用,但是此調用將返回一個表示著此接口值的動態類型的 reflect.Type 值。
實際上,reflect.TypeOf 函數的唯一參數的類型為 interface{},reflect.TypeOf 函數將總是返回一個表示著此唯一接口參數值的動態類型的 reflect.Type 值。
那如何得到一個表示著某個接口類型的 reflect.Type 值呢?我們必須通過下面將要介紹的一些間接途徑來達到這一目的。
類型 reflect.Type 為一個接口類型,它指定瞭若幹方法(https://golang.google.cn/pkg/reflect/#Type)。 通過這些方法,我們能夠觀察到一個 reflect.Type 值所表示的 Go類型的各種信息。這些方法中的有的適用於所有種類(https://golang.google.cn/pkg/reflect/#Kind)的類型,有的隻適用於一種或幾種類型。通過不合適的 reflect.Type 屬主值調用某個方法將在運行時產生一個恐慌。
使用 reflect.TypeOf() 函數可以獲得任意值的類型對象(reflect.Type),程序通過類型對象可以訪問任意值的類型信息。下面通過例子來理解獲取類型對象的過程:
package main import ( "fmt" "reflect" ) func main() { var a int typeOfA := reflect.TypeOf(a) fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
代碼輸出如下:
int int
代碼說明如下:
- 第 10 行,定義一個 int 類型的變量。
- 第 12 行,通過 reflect.TypeOf() 取得變量 a 的類型對象 typeOfA,類型為 reflect.Type()。
- 第 14 行中,通過 typeOfA 類型對象的成員函數,可以分別獲取到 typeOfA 變量的類型名為 int,種類(Kind)為 int。
理解反射的類型(Type)與種類(Kind)
在使用反射時,需要首先理解類型(Type)和種類(Kind)的區別。編程中,使用最多的是類型,但在反射中,當需要區分一個大品種的類型時,就會用到種類(Kind)。例如,需要統一判斷類型中的指針時,使用種類(Kind)信息就較為方便。
1) 反射種類(Kind)的定義
Go 程序中的類型(Type)指的是系統原生數據類型,如 int、string、bool、float32 等類型,以及使用 type 關鍵字定義的類型,這些類型的名稱就是其類型本身的名稱。例如使用 type A struct{} 定義結構體時,A 就是 struct{} 的類型。
種類(Kind)指的是對象歸屬的品種,在 reflect 包中有如下定義:
type Kind uint const ( Invalid Kind = iota // 非法類型 Bool // 佈爾型 Int // 有符號整型 Int8 // 有符號8位整型 Int16 // 有符號16位整型 Int32 // 有符號32位整型 Int64 // 有符號64位整型 Uint // 無符號整型 Uint8 // 無符號8位整型 Uint16 // 無符號16位整型 Uint32 // 無符號32位整型 Uint64 // 無符號64位整型 Uintptr // 指針 Float32 // 單精度浮點數 Float64 // 雙精度浮點數 Complex64 // 64位復數類型 Complex128 // 128位復數類型 Array // 數組 Chan // 通道 Func // 函數 Interface // 接口 Map // 映射 Ptr // 指針 Slice // 切片 String // 字符串 Struct // 結構體 UnsafePointer // 底層指針 )
Map、Slice、Chan 屬於引用類型,使用起來類似於指針,但是在種類常量定義中仍然屬於獨立的種類,不屬於 Ptr。
type A struct{} 定義的結構體屬於 Struct 種類,*A 屬於 Ptr。
2) 從類型對象中獲取類型名稱和種類的例子
Go語言中的類型名稱對應的反射獲取方法是 reflect.Type 中的 Name() 方法,返回表示類型名稱的字符串。
類型歸屬的種類(Kind)使用的是 reflect.Type 中的 Kind() 方法,返回 reflect.Kind 類型的常量。
下面的代碼中會對常量和結構體進行類型信息獲取。
package main import ( "fmt" "reflect" ) // 定義一個Enum類型 type Enum int const ( Zero Enum = 0 ) func main() { // 聲明一個空結構體 type cat struct { } // 獲取結構體實例的反射類型對象 typeOfCat := reflect.TypeOf(cat{}) // 顯示反射類型對象的名稱和種類 fmt.Println(typeOfCat.Name(), typeOfCat.Kind()) // 獲取Zero常量的反射類型對象 typeOfA := reflect.TypeOf(Zero) // 顯示反射類型對象的名稱和種類 fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
代碼輸出如下:
cat struct
Enum int
代碼說明如下:
- 第 18 行,聲明結構體類型 cat。
- 第 22 行,將 cat 實例化,並且使用 reflect.TypeOf() 獲取被實例化後的 cat 的反射類型對象。
- 第 25 行,輸出cat的類型名稱和種類,類型名稱就是 cat,而 cat 屬於一種結構體種類,因此種類為 struct。
- 第 28 行,Zero 是一個 Enum 類型的常量。這個 Enum 類型在第 9 行聲明,第 12 行聲明瞭常量。如沒有常量也不能創建實例,通過 reflect.TypeOf() 直接獲取反射類型對象。
- 第 31 行,輸出 Zero 對應的類型對象的類型名和種類。
到此這篇關於Go語言reflect.TypeOf()和reflect.Type通過反射獲取類型信息 的文章就介紹到這瞭,更多相關Go 反射獲取類型信息 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- None Found