Go語(yǔ)言reflect.TypeOf()和reflect.Type通過(guò)反射獲取類(lèi)型信息
在 Go語(yǔ)言中通過(guò)調(diào)用 reflect.TypeOf 函數(shù),我們可以從一個(gè)任何非接口類(lèi)型的值創(chuàng)建一個(gè) reflect.Type 值。reflect.Type 值表示著此非接口值的類(lèi)型。通過(guò)此值,我們可以得到很多此非接口類(lèi)型的信息。當(dāng)然,我們也可以將一個(gè)接口值傳遞給一個(gè) reflect.TypeOf 函數(shù)調(diào)用,但是此調(diào)用將返回一個(gè)表示著此接口值的動(dòng)態(tài)類(lèi)型的 reflect.Type 值。
實(shí)際上,reflect.TypeOf 函數(shù)的唯一參數(shù)的類(lèi)型為 interface{},reflect.TypeOf 函數(shù)將總是返回一個(gè)表示著此唯一接口參數(shù)值的動(dòng)態(tài)類(lèi)型的 reflect.Type 值。
那如何得到一個(gè)表示著某個(gè)接口類(lèi)型的 reflect.Type 值呢?我們必須通過(guò)下面將要介紹的一些間接途徑來(lái)達(dá)到這一目的。
類(lèi)型 reflect.Type 為一個(gè)接口類(lèi)型,它指定了若干方法(https://golang.google.cn/pkg/reflect/#Type)。 通過(guò)這些方法,我們能夠觀察到一個(gè) reflect.Type 值所表示的 Go類(lèi)型的各種信息。這些方法中的有的適用于所有種類(lèi)(https://golang.google.cn/pkg/reflect/#Kind)的類(lèi)型,有的只適用于一種或幾種類(lèi)型。通過(guò)不合適的 reflect.Type 屬主值調(diào)用某個(gè)方法將在運(yùn)行時(shí)產(chǎn)生一個(gè)恐慌。
使用 reflect.TypeOf() 函數(shù)可以獲得任意值的類(lèi)型對(duì)象(reflect.Type),程序通過(guò)類(lèi)型對(duì)象可以訪問(wèn)任意值的類(lèi)型信息。下面通過(guò)例子來(lái)理解獲取類(lèi)型對(duì)象的過(guò)程:
package main import ( "fmt" "reflect" ) func main() { var a int typeOfA := reflect.TypeOf(a) fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
代碼輸出如下:
int int
代碼說(shuō)明如下:
- 第 10 行,定義一個(gè) int 類(lèi)型的變量。
- 第 12 行,通過(guò) reflect.TypeOf() 取得變量 a 的類(lèi)型對(duì)象 typeOfA,類(lèi)型為 reflect.Type()。
- 第 14 行中,通過(guò) typeOfA 類(lèi)型對(duì)象的成員函數(shù),可以分別獲取到 typeOfA 變量的類(lèi)型名為 int,種類(lèi)(Kind)為 int。
理解反射的類(lèi)型(Type)與種類(lèi)(Kind)
在使用反射時(shí),需要首先理解類(lèi)型(Type)和種類(lèi)(Kind)的區(qū)別。編程中,使用最多的是類(lèi)型,但在反射中,當(dāng)需要區(qū)分一個(gè)大品種的類(lèi)型時(shí),就會(huì)用到種類(lèi)(Kind)。例如,需要統(tǒng)一判斷類(lèi)型中的指針時(shí),使用種類(lèi)(Kind)信息就較為方便。
1) 反射種類(lèi)(Kind)的定義
Go 程序中的類(lèi)型(Type)指的是系統(tǒng)原生數(shù)據(jù)類(lèi)型,如 int、string、bool、float32 等類(lèi)型,以及使用 type 關(guān)鍵字定義的類(lèi)型,這些類(lèi)型的名稱(chēng)就是其類(lèi)型本身的名稱(chēng)。例如使用 type A struct{} 定義結(jié)構(gòu)體時(shí),A 就是 struct{} 的類(lèi)型。
種類(lèi)(Kind)指的是對(duì)象歸屬的品種,在 reflect 包中有如下定義:
type Kind uint const ( Invalid Kind = iota // 非法類(lèi)型 Bool // 布爾型 Int // 有符號(hào)整型 Int8 // 有符號(hào)8位整型 Int16 // 有符號(hào)16位整型 Int32 // 有符號(hào)32位整型 Int64 // 有符號(hào)64位整型 Uint // 無(wú)符號(hào)整型 Uint8 // 無(wú)符號(hào)8位整型 Uint16 // 無(wú)符號(hào)16位整型 Uint32 // 無(wú)符號(hào)32位整型 Uint64 // 無(wú)符號(hào)64位整型 Uintptr // 指針 Float32 // 單精度浮點(diǎn)數(shù) Float64 // 雙精度浮點(diǎn)數(shù) Complex64 // 64位復(fù)數(shù)類(lèi)型 Complex128 // 128位復(fù)數(shù)類(lèi)型 Array // 數(shù)組 Chan // 通道 Func // 函數(shù) Interface // 接口 Map // 映射 Ptr // 指針 Slice // 切片 String // 字符串 Struct // 結(jié)構(gòu)體 UnsafePointer // 底層指針 )
Map、Slice、Chan 屬于引用類(lèi)型,使用起來(lái)類(lèi)似于指針,但是在種類(lèi)常量定義中仍然屬于獨(dú)立的種類(lèi),不屬于 Ptr。
type A struct{} 定義的結(jié)構(gòu)體屬于 Struct 種類(lèi),*A 屬于 Ptr。
2) 從類(lèi)型對(duì)象中獲取類(lèi)型名稱(chēng)和種類(lèi)的例子
Go語(yǔ)言中的類(lèi)型名稱(chēng)對(duì)應(yīng)的反射獲取方法是 reflect.Type 中的 Name() 方法,返回表示類(lèi)型名稱(chēng)的字符串。
類(lèi)型歸屬的種類(lèi)(Kind)使用的是 reflect.Type 中的 Kind() 方法,返回 reflect.Kind 類(lèi)型的常量。
下面的代碼中會(huì)對(duì)常量和結(jié)構(gòu)體進(jìn)行類(lèi)型信息獲取。
package main import ( "fmt" "reflect" ) // 定義一個(gè)Enum類(lèi)型 type Enum int const ( Zero Enum = 0 ) func main() { // 聲明一個(gè)空結(jié)構(gòu)體 type cat struct { } // 獲取結(jié)構(gòu)體實(shí)例的反射類(lèi)型對(duì)象 typeOfCat := reflect.TypeOf(cat{}) // 顯示反射類(lèi)型對(duì)象的名稱(chēng)和種類(lèi) fmt.Println(typeOfCat.Name(), typeOfCat.Kind()) // 獲取Zero常量的反射類(lèi)型對(duì)象 typeOfA := reflect.TypeOf(Zero) // 顯示反射類(lèi)型對(duì)象的名稱(chēng)和種類(lèi) fmt.Println(typeOfA.Name(), typeOfA.Kind()) }
代碼輸出如下:
cat struct
Enum int
代碼說(shuō)明如下:
- 第 18 行,聲明結(jié)構(gòu)體類(lèi)型 cat。
- 第 22 行,將 cat 實(shí)例化,并且使用 reflect.TypeOf() 獲取被實(shí)例化后的 cat 的反射類(lèi)型對(duì)象。
- 第 25 行,輸出cat的類(lèi)型名稱(chēng)和種類(lèi),類(lèi)型名稱(chēng)就是 cat,而 cat 屬于一種結(jié)構(gòu)體種類(lèi),因此種類(lèi)為 struct。
- 第 28 行,Zero 是一個(gè) Enum 類(lèi)型的常量。這個(gè) Enum 類(lèi)型在第 9 行聲明,第 12 行聲明了常量。如沒(méi)有常量也不能創(chuàng)建實(shí)例,通過(guò) reflect.TypeOf() 直接獲取反射類(lèi)型對(duì)象。
- 第 31 行,輸出 Zero 對(duì)應(yīng)的類(lèi)型對(duì)象的類(lèi)型名和種類(lèi)。
到此這篇關(guān)于Go語(yǔ)言reflect.TypeOf()和reflect.Type通過(guò)反射獲取類(lèi)型信息 的文章就介紹到這了,更多相關(guān)Go 反射獲取類(lèi)型信息 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go基礎(chǔ)教程系列之回調(diào)函數(shù)和閉包詳解
這篇文章主要介紹了Go基礎(chǔ)教程系列之回調(diào)函數(shù)和閉包詳解,需要的朋友可以參考下2022-04-04Go項(xiàng)目開(kāi)發(fā)中如何讀取應(yīng)用配置詳解
本文主要介紹了Go項(xiàng)目開(kāi)發(fā)中如何讀取應(yīng)用配置詳解,Go生態(tài)中有很多包可以加載并解析配置,最受歡迎的是Viper包,下面就來(lái)詳細(xì)的介紹一下2024-05-05Go語(yǔ)言Grpc?Stream的實(shí)現(xiàn)
本文主要介紹了Go語(yǔ)言Grpc?Stream的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Golang開(kāi)發(fā)中如何解決共享變量問(wèn)題
Go提供了傳統(tǒng)通過(guò)共享變量,也就是共享內(nèi)存的方式來(lái)實(shí)現(xiàn)并發(fā)。這篇文章會(huì)介紹 Go提供的相關(guān)機(jī)制,對(duì)Golang共享變量相關(guān)知識(shí)感興趣的朋友一起看看吧2021-09-09Go?gRPC進(jìn)階教程服務(wù)超時(shí)設(shè)置
這篇文章主要為大家介紹了Go?gRPC進(jìn)階,gRPC請(qǐng)求的超時(shí)時(shí)間設(shè)置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06VScode下配置Go語(yǔ)言開(kāi)發(fā)環(huán)境(2023最新)
在VSCode中配置Golang開(kāi)發(fā)環(huán)境是非常簡(jiǎn)單的,本文主要記錄了Go的安裝,以及給vscode配置Go的環(huán)境,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10Golang使用切片實(shí)現(xiàn)單鏈表的示例代碼
單鏈表(Single?Linked?List)是鏈表數(shù)據(jù)結(jié)構(gòu)的一種實(shí)現(xiàn)方式,它包含一系列節(jié)點(diǎn)(Node),每個(gè)節(jié)點(diǎn)都包含一個(gè)數(shù)據(jù)域和一個(gè)指向下一個(gè)節(jié)點(diǎn)的指針,本文給大家介紹了Golang使用切片實(shí)現(xiàn)單鏈表的操作,需要的朋友可以參考下2024-05-05