0

我想知道是否有可能不知道函数名但无论如何调用它并从中获取值。这将我带到了反射包,我非常接近,但我不确定最后一步 - 如果有的话。如果我遗漏了一些明显的东西,请再次原谅我,这是我第一次尝试在 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
4

2 回答 2

0

要获取作为 ModuleInfo 的返回值,请获取第一个返回值的基础值并将该接口值类型断言到 ModuleInfo:

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

在操场上运行它

您可以通过将方法断言到具有正确签名的函数并直接调用该函数来削减一些反射代码:

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("")
}

在操场上运行

于 2018-10-26T00:03:21.393 回答
0

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)

请注意,函数名后面没有括号:您将函数本身作为参数传递,而不是调用函数并传递其返回值。

于 2018-10-26T02:03:38.320 回答