duange051858 2017-12-04 01:42
浏览 17

函数和参数解组在哪里?

Given an interface containing functions with varying parameters and a concrete implementation of that interface how do I take a stream of bytes and call methods from the interface based on that byte stream. Basically an RPC call.

e.g.

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

And lets say I had the following input data

Hello John
Add 1 2 3 4

I figure this has to be done with reflection but this package I find a bit of mystery to use. Not great examples. Looking at RPC packages is also a bit mysterious. I don't understand what they are doing and there seem to be limitations or assumptions, perhaps to make the code simpler and/or faster to implement.

Can someone shed some light on how I might take the string "Hello" and find the function handle "Hello" from the funcs table. And know that it's expecting a single parameter that is a string and then calling that function with the argument provided "John".

  • 写回答

1条回答 默认 最新

  • duanmei1885 2017-12-04 02:20
    关注

    You can do this using the reflect package (general caveats about performance and code readability apply). Just create a type and implement the functions for that type, then call reflect.MethodByName() on a Value created from an instance of that type:

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

    This prints:

    Hello, Asha Returned [Asha <error Value>]

    (See https://play.golang.org/p/0q1i3WBuAL)

    However, if you know the function names you want to be able to call a priori, or if you want the user to be able to use names other than the exact function name, just use a switch or if/else statement:

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

    This prints:

    Hello, 재은

    (See https://play.golang.org/p/oBxsI42q4a)

    评论

报告相同问题?

悬赏问题

  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计