簡體   English   中英

使用Go Reflect調用函數

[英]Calling a function with Go Reflect

我想知道是否有可能不知道函數名而是無論如何都要調用它並從中獲取值。 這使我進入了反射包,我已經接近了,但是我不確定最后一步-如果有的話。 同樣,如果我遺漏了一些明顯的東西,請原諒我,這是我第一次嘗試在Go中做任何事情,而不是進行設置。

當然,作為一種編譯語言,不需要遍歷所有內容來查找函數名稱,我都知道它們,但這是我想看看是否有可能……我正在學習。

下面是代碼。 我真正想做的是在主行中提取在ModuleBoot()<“ 1.0012”,23>和SomethingBoot()<“ 1.0000”,10>中設置的值,但到目前為止,我所能獲得的只是結構信息。 也許就是這樣,但是也許有一個步驟或變更可以使它邁出下一步。

希望我正確地復制了所有相關代碼,以便按原樣編譯:

// Using: go version go1.9.7 linux/amd64
=======================================
FILE: main.go
=======================================
package main

import (
  "fmt"
  "reflect"
  "playing/modules/core"
)

func main() {

  miType := reflect.TypeOf(core.ModuleInfo{})

  fmt.Println("")

  for i := 0; i < miType.NumMethod(); i++ {
    method := miType.Method(i)
    fmt.Println(method.Name)

    in := make([]reflect.Value, method.Type.NumIn())
    in[0] = reflect.ValueOf(core.ModuleInfo{})
    //fmt.Println("Params in:", method.Type.NumIn(), "Params out:", method.Type.NumOut())

    mi := method.Func.Call(in)
    fmt.Println("mi:", mi)

    fmt.Println("")
  }
}

=======================================
FILE: playing/modules/core/something.go
=======================================
package core

func (mi ModuleInfo) SomethingBoot() ModuleInfo {
  mi.Version = "1.0000"
  mi.Priority = 10
  return mi
}

=======================================
FILE: playing/modules/core/modules.go
=======================================
package core

type ModuleInfo struct {
  Version string
  Priority int
}

func (mi ModuleInfo) ModuleBoot() ModuleInfo {
  mi.Version = "1.0012"
  mi.Priority = 23
  return mi
}

我從中得到的輸出是:

Started delve with config "Debug"

SomethingBoot
mi: [<core.ModuleInfo Value>]

ModuleBoot
mi: [<core.ModuleInfo Value>]

delve closed with code 0

為了得到返回值作為ModuleInfo,獲得潛在價值的第一個返回值和輸入斷言該接口值ModuleInfo:

// mi has type core.ModuleInfo
mi := method.Func.Call(in)[0].Interface().(core.ModuleInfo)

在Playground上運行它

您可以通過將方法斷言為具有正確簽名的函數並直接調用該函數來剪切一些反射代碼:

for i := 0; i < miType.NumMethod(); i++ {
    method := miType.Method(i).Func.Interface().(func(core.ModuleInfo) core.ModuleInfo)
    mi := method(core.ModuleInfo{})
    fmt.Println("Version", mi.Version)
    fmt.Println("Priority", mi.Priority)
    fmt.Println("")
}

在操場上運行

Go本身支持將功能作為值; 您不需要進行反思。

特別是,如果您將兩個函數設為頂級函數(未專門與結構綁定):

package core
type ModuleInfo struct { ... }
func SomethingBoot() ModuleInfo
func ModuleBoot() ModuleInfo

然后,您可以編寫一個將函數作為參數的函數:

func PrintVersion(func booter() core.ModuleInfo) {
        mi := booter()
        fmt.Printf("version %s\n", mi.Version)
}

您只需傳遞預先存在的函數作為參數即可:

PrintVersion(core.SomethingBoot)
PrintVersion(core.ModuleBoot)

請注意,函數名稱后沒有括號:您將函數本身作為參數傳遞,而不是調用函數並傳遞其返回值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM