go中的函数和参数unmarshalling?

时间:2017-12-04 01:42:46

标签: go

给定包含具有不同参数的函数的接口以及该接口的具体实现,如何从该接口基于该字节流获取字节流和调用方法。基本上是一个RPC调用。

e.g。

type funcs interface {
  func Hello(name string) (string, error)
  func Add(numbers...int) (result, error)
}

让我说我有以下输入数据

Hello John
Add 1 2 3 4

我认为这必须用反射来完成,但这个包我觉得有点神秘。不是很好的例子。看看RPC包也有点神秘。我不明白他们在做什么,似乎有限制或假设,也许是为了使代码更简单和/或更快实现。

有人可以说明我如何接受字符串"你好"并找到函数句柄" Hello"来自funcs表。并且知道它期望单个参数是一个字符串,然后使用提供的参数调用该函数" John"。

1 个答案:

答案 0 :(得分:1)

您可以使用reflect包执行此操作(有关性能和代码可读性的一般警告适用)。只需创建一个类型并实现该类型的函数,然后在从该类型的实例创建的Value上调用reflect.MethodByName()

package main

import (
    "fmt"
    "reflect"
)

type functions struct {}

func (f functions) Hello(name string) (string, error) {
    fmt.Println("Hello,", name)
    return name, nil
}

func main() {
    var f functions
    m := reflect.ValueOf(f).MethodByName("Hello")
    if m.IsValid() {
        // Either call f.Hello() here, or use the returned Value like so:
        v := make([]reflect.Value, 1) // function Values only take Value slices as arguments
        v[0] = reflect.ValueOf("Asha")
        r := m.Call(v)
        fmt.Println("Returned", r)
    }
}

打印:

Hello, Asha Returned [Asha <error Value>]

(见https://play.golang.org/p/0q1i3WBuAL

但是,如果您知道希望能够调用先验的函数名称,或者您希望用户能够使用除确切函数名称以外的名称,那么只需使用switchif / else声明:

package main

import (
    "fmt"
    "strings"
)

func Hello(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    userInput := make([]string, 2)
    userInput[0] = "HeLlO"
    userInput[1] = "재은"

    switch(strings.ToLower(userInput[0])) { // allow any case
    case "hello":
        Hello(userInput[1])
    default:
        panic("user input not recognized")
    }
}

打印:

Hello, 재은

(见https://play.golang.org/p/oBxsI42q4a