網(wǎng)站首頁 編程語言 正文
引言
這算是一個高級用法了,前面我們只說到對類型、變量的幾種反射的用法,包括如何獲取其值、其類型、以及如何重新設置新值。但是在項目應用中,另外一個常用并且屬于高級的用法,就是通過reflect來進行方法【函數(shù)】的調(diào)用。比如我們要做框架工程的時候,需要可以隨意擴展方法,或者說用戶可以自定義方法,那么我們通過什么手段來擴展讓用戶能夠自定義呢?關鍵點在于用戶的自定義方法是未可知的,因此我們可以通過reflect來搞定。
func (Value)?Call
func (v Value) Call(in []Value) []Value
Call方法使用輸入的參數(shù)in調(diào)用v持有的函數(shù)。例如,如果len(in) == 3,v.Call(in)代表調(diào)用v(in[0], in[1], in[2])(其中Value值表示其持有值)。如果v的Kind不是Func會panic。它返回函數(shù)所有輸出結(jié)果的Value封裝的切片。和go代碼一樣,每一個輸入實參的持有值都必須可以直接賦值給函數(shù)對應輸入?yún)?shù)的類型。如果v持有值是可變參數(shù)函數(shù),Call方法會自行創(chuàng)建一個代表可變參數(shù)的切片,將對應可變參數(shù)的值都拷貝到里面。
通過反射,調(diào)用方法。
先獲取結(jié)構(gòu)體對象,然后調(diào)用結(jié)構(gòu)體的方法。
示例代碼:
package main import ( "fmt" "reflect" ) type Person struct { Name string Age int Sex string } func (p Person)Say(msg string) { fmt.Println("hello,",msg) } func (p Person)PrintInfo() { fmt.Printf("姓名:%s,年齡:%d,性別:%s\n",p.Name,p.Age,p.Sex) } func (p Person) Test(i,j int,s string){ fmt.Println(i,j,s) } // 如何通過反射來進行方法的調(diào)用? // 本來可以用結(jié)構(gòu)體對象.方法名稱()直接調(diào)用的, // 但是如果要通過反射, // 那么首先要將方法注冊,也就是MethodByName,然后通過反射調(diào)動mv.Call func main() { p2 := Person{"王富貴",20,"男"} // 1. 要通過反射來調(diào)用起對應的方法,必須要先通過reflect.ValueOf(interface)來獲取到reflect.Value, // 得到“反射類型對象”后才能做下一步處理 getValue := reflect.ValueOf(p2) // 2.一定要指定參數(shù)為正確的方法名 // 先看看沒有參數(shù)的調(diào)用方法 methodValue1 := getValue.MethodByName("PrintInfo") fmt.Printf("Kind : %s, Type : %s\n",methodValue1.Kind(),methodValue1.Type()) methodValue1.Call(nil) //沒有參數(shù),直接寫nil args1 := make([]reflect.Value, 0) //或者創(chuàng)建一個空的切片也可以 methodValue1.Call(args1) // 有參數(shù)的方法調(diào)用 methodValue2 := getValue.MethodByName("Say") fmt.Printf("Kind : %s, Type : %s\n",methodValue2.Kind(),methodValue2.Type()) args2 := []reflect.Value{reflect.ValueOf("反射機制")} methodValue2.Call(args2) methodValue3 := getValue.MethodByName("Test") fmt.Printf("Kind : %s, Type : %s\n",methodValue3.Kind(),methodValue3.Type()) args3 := []reflect.Value{reflect.ValueOf(5), reflect.ValueOf(2),reflect.ValueOf("you")} methodValue3.Call(args3) }
運行結(jié)果:
Kind : func, Type : func()
姓名:王富貴,年齡:20,性別:男
姓名:王富貴,年齡:20,性別:男
Kind : func, Type : func(string)
hello, 反射機制
Kind : func, Type : func(int, int, string)
5 2 you
通過反射,調(diào)用函數(shù)。
首先我們要先確認一點,函數(shù)像普通的變量一樣,之前的章節(jié)中我們在講到函數(shù)的本質(zhì)的時候,是可以把函數(shù)作為一種變量類型的,而且是引用類型。如果說Fun()是一個函數(shù),那么f1 := Fun也是可以的,那么f1也是一個函數(shù),如果直接調(diào)用f1(),那么運行的就是Fun()函數(shù)。
那么我們就先通過ValueOf()來獲取函數(shù)的反射對象,可以判斷它的Kind,是一個func,那么就可以執(zhí)行Call()進行函數(shù)的調(diào)用。
示例代碼:
package main import ( "fmt" "reflect" ) func main() { //函數(shù)的反射 f1 := fun1 value := reflect.ValueOf(f1) fmt.Printf("Kind : %s , Type : %s\n",value.Kind(),value.Type()) //Kind : func , Type : func() value2 := reflect.ValueOf(fun2) fmt.Printf("Kind : %s , Type : %s\n",value2.Kind(),value2.Type()) //Kind : func , Type : func(int, string) //通過反射調(diào)用函數(shù) value.Call(nil) value2.Call([]reflect.Value{reflect.ValueOf("hello"),reflect.ValueOf(61)}) } func fun1(){ fmt.Println("我是函數(shù)fun1(),無參的。") } func fun2(s string, i int){ fmt.Println("我是函數(shù)fun2(),有參數(shù):",s,i) }
運行結(jié)果:
Kind : func , Type : func()
Kind : func , Type : func(string, int)
我是函數(shù)fun1(),無參的。
我是函數(shù)fun2(),有參數(shù): hello 61
原文鏈接:https://juejin.cn/post/7103368005987336206
相關推薦
- 2022-06-23 分布式醫(yī)療掛號系統(tǒng)整合Gateway網(wǎng)關解決跨域問題_其它綜合
- 2022-05-21 C#編程之AOP編程思想_C#教程
- 2023-03-05 useCallback和useMemo的正確用法詳解_React
- 2022-10-16 python?os模塊使用方法介紹_python
- 2022-07-07 淺談Qt實現(xiàn)HTTP的Get/Post請求_C 語言
- 2023-01-05 Kotlin?協(xié)程與掛起函數(shù)及suspend關鍵字深入理解_Android
- 2022-07-15 C++?DLL動態(tài)庫的創(chuàng)建與調(diào)用(類庫,隱式調(diào)用)_C 語言
- 2022-03-26 C語言goto語句簡單使用詳解_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支