golang反射中函式和方法的呼叫

2021-06-16 11:23:12 字數 2392 閱讀 6788

眾所周知,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 這是有乙個型別引數的情況 但是 獲取泛型方法不能新增佔位符 直接...