golang反射中函數和方法的調用

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

golang反射中函數和方法的調用

上一篇文章說到了golang中的反射的一些基本規則,重點就是文章中最後的三點,但是這篇文章並沒有說如何在反射中調用函數和方法,這就是接下來要談的。

反射中調用函數

眾所周知,golang中的函數是可以像普通的int、float等類型變數那樣作為值的,例如:

package mainimport "fmt"func hello() {  fmt.Println("Hello world!")}func main() {  hl := hello  hl()}

prints:

hello world!

既然函數可以像普通的類型變數一樣可以的話,那麼在反射機制中就和不同的變數一樣的,在反射中函數和方法的類型(Type)都是reflect.Func,如果要調用函數的話,可以通過Value的Call方法,例如:

func main() {  hl := hello  fv := reflect.ValueOf(hl)  fmt.Println("fv is reflect.Func ?",fv.Kind() == reflect.Func)  fv.Call(nil)}

prints:

fv is reflect.Func? truehello world!

Value的Call方法的參數是一個Value的slice,對應的反射函數類型的參數,傳回值也是一個Value的slice,同樣對應反射函數類型的傳回值。通過這個例子,相信你一看就明白了:

func prints(i int) string {  fmt.Println("i =",i)  return strconv.Itoa(i)}func main() {  fv := reflect.ValueOf(prints)  params := make([]reflect.Value,1)  //參數  params[0] := reflect.ValueOf(20)   //參數設定為20  rs := fv.Call(params)              //rs作為結果接受函數的傳回值  fmt.Println("result:",rs[0].Interface().(string)) //當然也可以直接是rs[0].Interface()}

prints:

i = 20result: 20

反射中調用方法

上面說了在反射中調用函數的例子,接下來我們要談談反射中方法的調用。函數和方法可以說其實本質上是相同的,只不過方法與一個“對象”進行了“綁定”,方法是“對象”的一種行為,這種行為是對於這個“對象”的一系列操作,例如修改“對象”的某個屬性,例如如下:

type MyType struct {  i int  name string}func (mt *MyType) SetI(i int) {  mt.i = i}func (mt *MyType) SetName(name string) {  mt.name = name}func (mt *MyType) String() string {  return fmt.Sprintf("%p",mt) + "--name:" + mt.name + " i:" + strconv.Itoa(mt.i) }

好了,現在類型和其對應的方法都已經準備好了,那接下來就是如何使用的問題了,我們有了上面調用函數的經驗,只需要再瞭解一點知識就可以使用了,這一點知識就是Method和MethodByName的API,好了,現在都準備好了,我們就看看如何使用吧。

func main() {  myType := &MyType{22,wowzai}  //fmt.Println(myType)     //就是檢查一下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:22After: 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])

列印的效果和上面的例子相同(地址可能不同),嗯,到這裡基本上反射中函數和方法的調用基本說完了,可是真的結束了?是否還有其他辦法呢?嗯,聰明的你總能想得到的。

---如有錯誤,歡迎指正---

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.