Go REFLECT Library反射類型詳解
一、反射概述
反射是指程序在運行期間對程序本身進(jìn)行訪問和修改的能力。程序在編譯過程中變量會被轉(zhuǎn)換為內(nèi)存地址,變量名不會被編譯器寫入到可執(zhí)行部分。在程序運行時程序無法獲取自身的信息。
在靜態(tài)語言中如 Java 可以在程序編譯期將變量的反射信息,如字段名稱、類型等信息整合到可執(zhí)行文件中,并給程序提供接口訪問反射信息,這樣就可以在程序運行期獲取類型的反射信息,并修改該它們。
對于動態(tài)語言來說如 Ruby 的動態(tài)特性相比靜態(tài)語言來說可以非常簡單的在程序運行時訪問變量、方法或者對象信息,也可以修改它們,甚至可以動態(tài)性可以讓程序自己構(gòu)造并執(zhí)行代碼,這就是元編程。
Ruby 中的基類(Object)包含了方法 methods、常量 constants 和實例變量instance_variable 的動態(tài)獲取。
puts String.method_defined?(:upcase) # 判斷是否定義了 upcase 方法
puts String.methods # 獲取所有方法
puts Math.const_get("PI") # 獲取常量
puts Math.const_set("PII", 1000) # 設(shè)置常量
puts Math.const_defined?(:P) # 判斷是否包含指定常量
puts Math.constants # 獲取所有常量
因此 Ruby 這里動態(tài)解釋型語言是反射系統(tǒng)的,但是 Go 作為一門靜態(tài)編譯型語言提供了 relect 標(biāo)準(zhǔn)庫訪問程序的反射信息。
Go 語言的反射系統(tǒng)無法獲取到一個可執(zhí)行文件空間中或者是一個包中所有類型信息,需要配合使用標(biāo)準(zhǔn)庫中對應(yīng)的詞法和語法解析器和抽象語法書對源碼進(jìn)行掃描后獲取這些信息

二、反射類型對象
基本數(shù)類型的 反射類型對象
在 Go 中使用 reflect 標(biāo)準(zhǔn)庫下的 typeOf 函數(shù)可以獲取任意變量的反射類型對象,程序通過 反射類型對象 可以訪問任意變量的類型信息。
func main(){
zulu := "stark"
zuluType := reflect.TypeOf(zulu)
fmt.Printf("zuluType 的類型為:%v,類型名為:%v,種類為:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
執(zhí)行上述代碼,輸出結(jié)果如下:
zuluType 的類型為:string,類型名為:string,種類為:string
TypeOf 函數(shù)返回一個 Type 接口,該接口包含非常多的方法

上述代碼中的類型就是變量的數(shù)據(jù)類型,如基本數(shù)據(jù)類型中的 int、int64、float64、string、map、bool 以及 type 結(jié)構(gòu)體類型等,類型名就是類型本身。

種類既 Kind 方法獲取的信息是指對象歸屬的品種,在 reflect 庫中對對象歸屬的 Kind 做了定義

Kind 的范圍在如下列出的常量中

并在通過 String() 方法做了小寫的轉(zhuǎn)換,最終返回 Kind 為 string

Name 和 Kind 可以表示一個變量的 反射類型對象 的信息。每種數(shù)據(jù)類型變量的 反射類型對象 的 Name 和 Kind 都是不同的。
引用數(shù)據(jù)類型的 反射類型對象
func main(){
zulu := map[string]string{
"name": "Stark",
"address": "NYC",
}
zuluType := reflect.TypeOf(zulu)
fmt.Printf("zuluType 的類型為:%v,類型名為:%v,種類為:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
執(zhí)行上述代碼,輸出結(jié)果如下:
zuluType 的類型為:map[string]string,類型名為:,種類為:map
Map、Array、Slice 和 Pointer 類型的 Name() 都為空字符串
結(jié)構(gòu)體的 反射類型對象
func main(){
zulu := Zulu{"stark", 33}
zuluType := reflect.TypeOf(zulu)
fmt.Printf("zuluType 的類型為:%v,類型名為:%v,種類為:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
type Zulu struct {
Name string
Age int
}
執(zhí)行上述代碼,輸出結(jié)果如下:
zuluType 的類型為:main.Zulu,類型名為:Zulu,種類為:struct
結(jié)構(gòu)體變量的 反射類型對象 的 Name 就是結(jié)構(gòu)體的名字,種類為 struct 結(jié)構(gòu)體
指針的 反射類型對象
func main(){
zulu := Zulu{"stark", 33}
// 定義一個指針
zuluPtr := &zulu
zuluType := reflect.TypeOf(zuluPtr)
fmt.Printf("zuluType 的類型為:%v,類型名為:%v,種類為:%v\n", zuluType, zuluType.Name(), zuluType.Kind())
}
type Zulu struct {
Name string
Age int
}
執(zhí)行上述代碼,輸出結(jié)果如下:
zuluType 的類型為:*main.Zulu,類型名為:,種類為:ptr
指針的 Name() 返回的也是空字符串。
在 main 函數(shù)中增加代碼
// 其余代碼保持不變,在 main 函數(shù)底部增加如下代碼。
// 使用反射類型對象(Type)獲取原類型
zuluTypeElem := zuluType.Elem()
fmt.Printf("zuluTypeElem 的類型為:%v,類型名為:%v,種類為:%v\n", zuluTypeElem, zuluTypeElem.Name(), zuluTypeElem.Kind())
執(zhí)行上述的代碼,輸出結(jié)果如下:
zuluType 的類型為:*main.Zulu,類型名為:,種類為:ptr
zuluTypeElem 的類型為:main.Zulu,類型名為:Zulu,種類為:struct
也就是說我們通過一個結(jié)構(gòu)體指針獲取了一個反射類型,在通過反射類型獲取到原結(jié)構(gòu)體

Go 中對指針獲取 反射類型對象 之后,可以通過獲取的 反射類型對象 的 Elem 方法獲取指針?biāo)鶊?zhí)行的元素的類型,這個過程被稱為取元素,就相當(dāng)于對指針執(zhí)行了 * 操作。
以上就是Go REFLECT Library反射類型詳解的詳細(xì)內(nèi)容,更多關(guān)于Go REFLECT Library反射類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入學(xué)習(xí)Golang并發(fā)編程必備利器之sync.Cond類型
Go?語言的?sync?包提供了一系列同步原語,其中?sync.Cond?就是其中之一。本文將深入探討?sync.Cond?的實現(xiàn)原理和使用方法,幫助大家更好地理解和應(yīng)用?sync.Cond,需要的可以參考一下2023-05-05
使用golang腳本基于kubeadm創(chuàng)建新的token(問題分析)
這篇文章主要介紹了使用golang腳本基于kubeadm創(chuàng)建新的token(問題分析),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-10-10
淺談goland導(dǎo)入自定義包時出錯(一招解決問題)
這篇文章主要介紹了淺談goland導(dǎo)入自定義包時出錯(一招解決問題),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

