眾所周知,golang中的函式是可以像普通的int、float等型別變數那樣作為值的,例如:
package main
import "fmt"
func hello()
func main()
prints:
hello world!
既然函式可以像普通的型別變數一樣可以的話,那麼在反射機制中就和不同的變數一樣的,在反射中函式和方法的型別(type)都是reflect.func,如果要呼叫函式的話,可以通過value的call方法,例如:
func main()
prints:
fv is reflect.func? true
hello world!
value的call方法的引數是乙個value的slice,對應的反射函式型別的引數,返回值也是乙個value的slice,同樣對應反射函式型別的返回值。通過這個例子,相信你一看就明白了:
func prints(i int) string
func main()
prints:
i = 20
result: 20
上面說了在反射中呼叫函式的例子,接下來我們要談談反射中方法的呼叫。函式和方法可以說其實本質上是相同的,只不過方法與乙個「物件」進行了「繫結」,方法是「物件」的一種行為,這種行為是對於這個「物件」的一系列操作,例如修改「物件」的某個屬性,例如如下:
type mytype struct
func (mt *mytype) seti(i int)
func (mt *mytype) setname(name string)
func (mt *mytype) string() string
好了,現在型別和其對應的方法都已經準備好了,那接下來就是如何使用的問題了,我們有了上面呼叫函式的經驗,只需要再了解一點知識就可以使用了,這一點知識就是method和methodbyname的api,好了,現在都準備好了,我們就看看如何使用吧。
func main()
//就是檢查一下mytype物件內容
//println("---------------")
mtv := reflect.valueof(&mytype).elem()
fmt.println("before:",mtv.methodbyname("string").call(nil)[0])
params := make(reflect.value,1)
params[0] = reflect.valueof(18)
mtv.methodbyname("seti").call(params)
params[0] = reflect.valueof("reflection test")
mtv.methodbyname("setname").call(params)
fmt.println("after:",mtv.methodbyname("string").call(nil)[0])
}
prints:
before: address:0x18245050--name:wowzai i:22
after: address:0x18245050--name:reflection test i:18
需要注意的是上面列印的位址是物件在記憶體的位址,如果你也執行了這段**,結果這個位址應該是不同的。
咦,就這樣結束了嗎?當然不是,細心的讀者會發現上面提到的method好像沒用到啊,恩,是的,聰明的你一看api的介紹我相信你就知道如何將上面的**轉換成用method方法達到同樣的效果:
mtv := reflect.valueof(&mytype).elem()
fmt.println("before:",mtv.method(2).call(nil)[0])
params = make(reflect.value,1)
params[0] = reflect.valueof(18)
mtv.method(0).call(params)
params[0] = reflect.valueof("reflection test")
mtv.method(1).call(params)
fmt.println("after:",mtv.method(2).call(nil)[0])
列印的效果和上面的例子相同(位址可能不同),嗯,到這裡基本上反射中函式和方法的呼叫基本說完了,可是真的結束了?是否還有其他辦法呢?嗯,聰明的你總能想得到的。
---如有錯誤,歡迎指正---
詳述反射中的方法
反射系列傳送門 如何獲取class類物件 詳述反射中的構造方法 詳述反射中的普通方法 本篇 詳述反射中的屬性 現有學生類如下 public class student private int dohousework int a,string scores 1 獲取所有public級別的方法,包括其父...
反射中屬性的用法
首先自定義屬性繼承 system.attribute attributeusage attributetatget.all,allowmultpie true,inherited false 關於自定義屬性的約束 作用範圍 可否多次設定 可否繼承 public class myattribute a...
C 基礎加固 三 呼叫反射中的方法
呼叫反射型別中的函式一種是 使用 動態型別dynamic直接呼叫,這裡對這種方法不深究 注意 反射查詢 泛型類的時候 需要指定 佔位符 如 var generictype dll.gettype tryref.genericcls 1 這是有乙個型別引數的情況 但是 獲取泛型方法不能新增佔位符 直接...