Go REFLECT Library反射類(lèi)型詳解
一、反射概述
反射是指程序在運(yùn)行期間對(duì)程序本身進(jìn)行訪問(wèn)和修改的能力。程序在編譯過(guò)程中變量會(huì)被轉(zhuǎn)換為內(nèi)存地址,變量名不會(huì)被編譯器寫(xiě)入到可執(zhí)行部分。在程序運(yùn)行時(shí)程序無(wú)法獲取自身的信息。
在靜態(tài)語(yǔ)言中如 Java 可以在程序編譯期將變量的反射信息,如字段名稱(chēng)、類(lèi)型等信息整合到可執(zhí)行文件中,并給程序提供接口訪問(wèn)反射信息,這樣就可以在程序運(yùn)行期獲取類(lèi)型的反射信息,并修改該它們。
對(duì)于動(dòng)態(tài)語(yǔ)言來(lái)說(shuō)如 Ruby 的動(dòng)態(tài)特性相比靜態(tài)語(yǔ)言來(lái)說(shuō)可以非常簡(jiǎn)單的在程序運(yùn)行時(shí)訪問(wèn)變量、方法或者對(duì)象信息,也可以修改它們,甚至可以動(dòng)態(tài)性可以讓程序自己構(gòu)造并執(zhí)行代碼,這就是元編程。
Ruby 中的基類(lèi)(Object)包含了方法 methods、常量 constants 和實(shí)例變量instance_variable 的動(dòng)態(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 這里動(dòng)態(tài)解釋型語(yǔ)言是反射系統(tǒng)的,但是 Go 作為一門(mén)靜態(tài)編譯型語(yǔ)言提供了 relect 標(biāo)準(zhǔn)庫(kù)訪問(wèn)程序的反射信息。
Go 語(yǔ)言的反射系統(tǒng)無(wú)法獲取到一個(gè)可執(zhí)行文件空間中或者是一個(gè)包中所有類(lèi)型信息,需要配合使用標(biāo)準(zhǔn)庫(kù)中對(duì)應(yīng)的詞法和語(yǔ)法解析器和抽象語(yǔ)法書(shū)對(duì)源碼進(jìn)行掃描后獲取這些信息

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

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

種類(lèi)既 Kind 方法獲取的信息是指對(duì)象歸屬的品種,在 reflect 庫(kù)中對(duì)對(duì)象歸屬的 Kind 做了定義

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

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

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

Go 中對(duì)指針獲取 反射類(lèi)型對(duì)象 之后,可以通過(guò)獲取的 反射類(lèi)型對(duì)象 的 Elem 方法獲取指針?biāo)鶊?zhí)行的元素的類(lèi)型,這個(gè)過(guò)程被稱(chēng)為取元素,就相當(dāng)于對(duì)指針執(zhí)行了 * 操作。
以上就是Go REFLECT Library反射類(lèi)型詳解的詳細(xì)內(nèi)容,更多關(guān)于Go REFLECT Library反射類(lèi)型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
go判斷文件夾是否存在并創(chuàng)建的實(shí)例
這篇文章主要介紹了go判斷文件夾是否存在,并創(chuàng)建的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
go中結(jié)構(gòu)體切片的實(shí)現(xiàn)示例
Go語(yǔ)言中的結(jié)構(gòu)體切片是一種結(jié)合了結(jié)構(gòu)體和切片特點(diǎn)的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)和操作多個(gè)結(jié)構(gòu)體實(shí)例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-11-11
Golang中重復(fù)錯(cuò)誤處理的優(yōu)化方法
這篇文章主要給大家介紹了關(guān)于Golang中重復(fù)錯(cuò)誤處理優(yōu)化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Go基礎(chǔ)教程系列之WaitGroup用法實(shí)例詳解
這篇文章主要介紹了Go基礎(chǔ)教程系列之WaitGroup用法實(shí)例詳解,需要的朋友可以參考下2022-04-04
淺析Go語(yǔ)言的數(shù)據(jù)類(lèi)型及數(shù)組
Golang是一種靜態(tài)強(qiáng)類(lèi)型、編譯型語(yǔ)言。Go?語(yǔ)言語(yǔ)法與?C?相近,但功能上有:內(nèi)存安全,GC(垃圾回收),結(jié)構(gòu)形態(tài)及?CSP-style?并發(fā)計(jì)算。本文主要和大家聊聊Go語(yǔ)言的數(shù)據(jù)類(lèi)型及數(shù)組,希望對(duì)大家有所幫助2022-11-11
go 判斷兩個(gè) slice/struct/map 是否相等的實(shí)例
這篇文章主要介紹了go 判斷兩個(gè) slice/struct/map 是否相等的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
Go語(yǔ)言單元測(cè)試的實(shí)現(xiàn)及用例
在日常開(kāi)發(fā)中,我們通常需要針對(duì)現(xiàn)有的功能進(jìn)行單元測(cè)試,以驗(yàn)證開(kāi)發(fā)的正確性,本文主要介紹了Go語(yǔ)言單元測(cè)試的實(shí)現(xiàn)及用例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01
Golang實(shí)現(xiàn)Dijkstra算法過(guò)程詳解
Dijkstra 算法是一種用于計(jì)算無(wú)向圖的最短路徑的算法,它是基于貪心策略的,每次選擇當(dāng)前距離起始節(jié)點(diǎn)最近的未訪問(wèn)節(jié)點(diǎn)進(jìn)行訪問(wèn),并更新其相鄰節(jié)點(diǎn)的距離值,以得到最短路徑,這篇文章主要介紹了Golang實(shí)現(xiàn)Dijkstra算法,需要的朋友可以參考下2023-05-05

