草庐IT

reflection - Go: reflect : 调用输入参数太少

coder 2024-07-11 原文

我一直坚持使用反射库的问题。由于很多推荐,我决定使用它,但我只是在学习,有些部分并不是很容易..

我有这部分代码:

 func countDataByName(sourceName string, statData interface{}, filters Filter, chartName string) []ChartElement {
            ...
    //step 1 - filter
    filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call([]reflect.Value{})

    //step 2 - cluster
    //  clusterData := reflect.ValueOf(filteredData).MethodByName("clusterData").Call([]reflect.Value{})

    //step 3 - count
    //  countedData := reflect.ValueOf(clusterData).MethodByName(chartName).Call([]reflect.Value{})

    fmt.Println("Never prints to anywhere", filteredData)

            ...
     return filterData
 }

如果我执行这样的方法,我会得到错误:reflect: Call with too few input arguments。但是,如果我在 reflect.ValueOf(&statData) 上更改 reflect.ValueOf(statData),则错误是 reflect: call of reflect.Value.Call on zero Value

statData 带有 2 种类型之一,在这种类型之前,我有结构和方法,如下所示:

type NoaggModel struct {
    Date             string
    Hour             int
    Id_user          int
    Id_line          int
    Id_region        int
    Id_tree_devision int
    N_inb            int
    N_inb_d          int
    T_ring           int
    T_inb            int
    T_inb_d          int
    T_hold           int
    T_acw            int
    T_acw_d          int
    T_wait           int
}

func (ng *NoaggModel) FilterData( data NoaggModel) {
    fmt.Println("FilterData")
    fmt.Println("data : ", data)
}

这个 Println 也不起作用。上面的代码崩溃,并且没有触发方法。我的错误在哪里?

更新 1:

发现如果我在我想调用的函数中删除参数 data,它会很好地调用。但! 我有 statData 作为结构的 1 行,所以类型是 NoaggModel。在 FilterData 方法中,我将这 1 行作为 ng 获取。但我需要将其更改为 []NoaggModel。在这种情况下如何调用 reflect 以及如何将参数传递给过滤器函数?

更新 2: 我修改了几个部分:

func (ng *NoaggModel) FilterData(filter interface{}, data NoaggModel) {
    fmt.Println("data : ",ng)
}

在这里,如何将正确的类型传递给 filter,如果它在 revel Controller 中设置,并且方法在模型中。或者我应该在每个模型中设置类型并在 Controller 中调用它?

我在 Controller 中写道:

//step 1 - filter
    in := make([]reflect.Value, 2)

    in[0] = reflect.ValueOf(filters)
    in[1] = reflect.ValueOf(statData)

    filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call(in)

StatData 是 NoaggModel 类型的一行,但我收到错误:

 reflect: Call using *models.NoaggModel as type models.NoaggModel 

类型也由上面代码中的 reflect 设置,如下所示:

    ...
    var sourceTypes = map[string]reflect.Type{
        "noagg": reflect.TypeOf(models.NoaggModel{}),
        "oracle": reflect.TypeOf(models.OracleModel{}),
    }
    deserializedData = reflect.New(sourceTypes[sourceName]).Interface()
    ...
    // deserialised becomes statData

最佳答案

反射(reflection)并不容易。并且应尽可能避免。

我承认我确实建议使用 reflect 来基于映射动态创建类型实例,当您不知道可能需要处理哪些类型时,这非常有用。但在您的情况下,您应该考虑使用接口(interface)。

虽然我真的不知道您想要实现什么,但我建议您首先创建一个所有模型都需要实现的接口(interface)(修改它以满足您的需求):

type Model interface {
    FilterData(interface{})
}

NoaggModelOracleModel 将通过定义如下类似方法来实现上述接口(interface):

func (ng *NoaggModel) FilterData(filter interface{}) {
    fmt.Printf("data: %#v, filter: %#v\n", ng, filter)
}

然后,将 deserializedData(和 statData)更改为接口(interface)类型 Model 而不是 interface{}。由于您只有两种类型,因此您可以通过切换来避免使用反射:

...
var deserializedData Model

switch sourceName {
case "noagg":
    deserializedData = new(models.NoaggModel)
case "oracle":
    deserializedData = new(models.OracleModel)
}
...
// Marshal the values into deserializedData which now holds an instance of the desired type
...
deserializedData.FilterData("Replace this string with your filter")

而且无需导入 reflect 即可完成!

关于reflection - Go: reflect : 调用输入参数太少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35429132/

有关reflection - Go: reflect : 调用输入参数太少的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  4. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  5. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  6. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  9. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐