網站首頁 編程語言 正文
一、反射概述
反射是指程序在運行期間對程序本身進行訪問和修改的能力。程序在編譯過程中變量會被轉換為內存地址,變量名不會被編譯器寫入到可執行部分。在程序運行時程序無法獲取自身的信息。
在靜態語言中如 Java 可以在程序編譯期將變量的反射信息,如字段名稱、類型等信息整合到可執行文件中,并給程序提供接口訪問反射信息,這樣就可以在程序運行期獲取類型的反射信息,并修改該它們。
對于動態語言來說如 Ruby 的動態特性相比靜態語言來說可以非常簡單的在程序運行時訪問變量、方法或者對象信息,也可以修改它們,甚至可以動態性可以讓程序自己構造并執行代碼,這就是元編程。
Ruby 中的基類(Object)包含了方法 methods
、常量 constants
和實例變量instance_variable
的動態獲取。
puts String.method_defined?(:upcase) # 判斷是否定義了 upcase 方法 puts String.methods # 獲取所有方法 puts Math.const_get("PI") # 獲取常量 puts Math.const_set("PII", 1000) # 設置常量 puts Math.const_defined?(:P) # 判斷是否包含指定常量 puts Math.constants # 獲取所有常量
因此 Ruby 這里動態解釋型語言是反射系統的,但是 Go 作為一門靜態編譯型語言提供了 relect
標準庫訪問程序的反射信息。
Go 語言的反射系統無法獲取到一個可執行文件空間中或者是一個包中所有類型信息,需要配合使用標準庫中對應的詞法和語法解析器和抽象語法書對源碼進行掃描后獲取這些信息
二、反射類型對象
基本數類型的 反射類型對象
在 Go 中使用 reflect
標準庫下的 typeOf
函數可以獲取任意變量的反射類型對象
,程序通過 反射類型對象
可以訪問任意變量的類型信息。
func main(){ zulu := "stark" zuluType := reflect.TypeOf(zulu) fmt.Printf("zuluType 的類型為:%v,類型名為:%v,種類為:%v\n", zuluType, zuluType.Name(), zuluType.Kind()) }
執行上述代碼,輸出結果如下:
zuluType 的類型為:string,類型名為:string,種類為:string
TypeOf
函數返回一個 Type 接口,該接口包含非常多的方法
上述代碼中的類型就是變量的數據類型,如基本數據類型中的 int、int64、float64、string、map、bool 以及 type 結構體類型等,類型名就是類型本身。
種類既 Kind
方法獲取的信息是指對象歸屬的品種,在 reflect
庫中對對象歸屬的 Kind 做了定義
Kind 的范圍在如下列出的常量中
并在通過 String()
方法做了小寫的轉換,最終返回 Kind 為 string
Name 和 Kind 可以表示一個變量的 反射類型對象
的信息。每種數據類型變量的 反射類型對象
的 Name 和 Kind 都是不同的。
引用數據類型的 反射類型對象
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()) }
執行上述代碼,輸出結果如下:
zuluType 的類型為:map[string]string,類型名為:,種類為:map
Map、Array、Slice 和 Pointer 類型的 Name()
都為空字符串
結構體的 反射類型對象
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 }
執行上述代碼,輸出結果如下:
zuluType 的類型為:main.Zulu,類型名為:Zulu,種類為:struct
結構體變量的 反射類型對象 的 Name 就是結構體的名字,種類為 struct 結構體
指針的 反射類型對象
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 }
執行上述代碼,輸出結果如下:
zuluType 的類型為:*main.Zulu,類型名為:,種類為:ptr
指針的 Name() 返回的也是空字符串。
在 main 函數中增加代碼
// 其余代碼保持不變,在 main 函數底部增加如下代碼。 // 使用反射類型對象(Type)獲取原類型 zuluTypeElem := zuluType.Elem() fmt.Printf("zuluTypeElem 的類型為:%v,類型名為:%v,種類為:%v\n", zuluTypeElem, zuluTypeElem.Name(), zuluTypeElem.Kind())
執行上述的代碼,輸出結果如下:
zuluType 的類型為:*main.Zulu,類型名為:,種類為:ptr
zuluTypeElem 的類型為:main.Zulu,類型名為:Zulu,種類為:struct
也就是說我們通過一個結構體指針獲取了一個反射類型,在通過反射類型獲取到原結構體
Go 中對指針獲取 反射類型對象
之后,可以通過獲取的 反射類型對象
的 Elem
方法獲取指針所執行的元素的類型,這個過程被稱為取元素,就相當于對指針執行了 *
操作。
原文鏈接:https://juejin.cn/post/7137731254190882824
相關推薦
- 2023-03-22 淺談C#中[]的幾種用法_C#教程
- 2022-09-15 python基于tkinter圖形化編程實現簡易計算器功能_python
- 2022-11-17 一文講解如何獲取k8s容器里運行的jar包_云其它
- 2022-02-24 Matlab中plot函數及legend函數詳解
- 2022-08-25 .net?core中高效的動態內存管理方案_實用技巧
- 2022-06-01 python機器學習sklearn實現識別數字_python
- 2022-06-25 python數據寫入Excel文件中的實現步驟_python
- 2022-03-10 .NET6一些常用組件的配置及使用_基礎應用
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支