简体   繁体   English

恐慌:反映:调用 reflect.Value.Call 零值

[英]panic: reflect: call of reflect.Value.Call on zero Value

I'm trying to use reflection in order to make a dynamic function call based on user input.我正在尝试使用反射来根据用户输入进行动态 function 调用。 I'm collecting user input like such:我正在收集这样的用户输入:

func main() {
    for {
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("> ")
        command, _ := reader.ReadString('\n')
        runCommandFromString(command)
    }
}

This is how the command is parsed out这就是命令被解析出来的方式

func stringCommandParser(cmd string) *Command {
    cmdParts := strings.Split(
        strings.TrimSpace(cmd),
        " ",
    )
    return &Command{
        Name: cmdParts[0],
        Args: cmdParts[1:],
    }
}

func runCommandFromString(cmd string) {
    command := stringCommandParser(cmd)

    c := &Commander{}
    f := reflect.ValueOf(&c).MethodByName(command.Name)
    inputs := []reflect.Value{reflect.ValueOf(command)}
    f.Call(inputs)
}

The commands.go file looks like this commands.go 文件如下所示

type Command struct {
    Name string
    Args []string
}

type Commander struct {}

func (c Commander) Hello(cmd Command) {
    fmt.Println("Meow", cmd.Args)
}

When I run the program, I get a prompt and I run a command called "Hello" with a param called "world".当我运行该程序时,我得到一个提示,然后我运行一个名为“Hello”的命令和一个名为“world”的参数。 I would expect "Meow [World]" or something like that to appear.我希望出现“Meow [World]”或类似的东西。 Like this:像这样:

> Hello world
Meow world

Instead what I get is a panic that looks like this:相反,我得到的是一个看起来像这样的恐慌:

> Hello world
panic: reflect: call of reflect.Value.Call on zero Value

goroutine 1 [running]:
panic(0x123360, 0xc420014360)
    /Users/parris/.gvm/gos/go1.7.4/src/runtime/panic.go:500 +0x1a1
reflect.flag.mustBe(0x0, 0x13)
    /Users/parris/.gvm/gos/go1.7.4/src/reflect/value.go:201 +0xae
reflect.Value.Call(0x0, 0x0, 0x0, 0xc420055e00, 0x1, 0x1, 0x0, 0x0, 0x0)
    /Users/parris/.gvm/gos/go1.7.4/src/reflect/value.go:300 +0x38
main.runCommandFromString(0xc42000c8a0, 0xc)
    /Users/parris/Projects/distro/main/utils.go:26 +0x1a0
main.main()
    /Users/parris/Projects/distro/main/main.go:14 +0x149
exit status 2

How can I fix this?我怎样才能解决这个问题? Also, what is happening?另外,这是怎么回事?

You might want to check what reflect.ValueOf returns before using it.您可能想在使用之前检查reflect.ValueOf返回的内容。

In this case you're getting a nil value because reflect can not see functions that aren't exported.在这种情况下,您将获得一个 nil 值,因为reflect 看不到未导出的函数。 hello starts with a lower case letter and therefore isn't exported. hello以小写字母开头,因此不会导出。

Also, you're making too many pointers here, I suspect that you need to do reflect.ValueOf(c) .另外,你在这里提出了太多的指针,我怀疑你需要做reflect.ValueOf(c) You're doing and debugging too many things at the same time.您同时在做和调试太多的事情。 Make a simple working example and continue debugging from there.制作一个简单的工作示例并从那里继续调试。

This works for me: https://play.golang.org/p/Yd-WDRzura这对我有用https : //play.golang.org/p/Yd-WDRzura

Just do two changes in your code.只需在您的代码中做两个更改。 First change reflect.ValueOf(&c) to reflect.ValueOf(c) Secondly change reflect.ValueOf(command) to reflect.ValueOf(*command)首先将reflect.ValueOf(&c) 更改为reflect.ValueOf(c) 其次将reflect.ValueOf(command) 更改为reflect.ValueOf(*command)

This is the code workingcode这是代码workingcode

Call Kind() to check调用 Kind() 检查

type Header struct {
    Token string
}
    
type Request struct {
    Header 
}   


func requestedToken(request interface{}) string {
    requestValue := reflect.ValueOf(request)
    header := requestValue.FieldByName("Header12")
    if header.Kind() == 0 {
        return "" //Return here
    }
    token := header.FieldByName("Token")
    if token.Kind() == 0 {
        return ""
    }
    return token.String()
}

您需要将runCommandFromString更改为RunCommandFromString

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Golang-为什么在ServeHTTP函数中发生此错误:反射:调用reflect.Value.Call对零值 - Golang - Why this error happened in ServeHTTP Function : reflect: call of reflect.Value.Call on zero Value 在golang程序中查找内存泄漏-reflect.Value.call的含义 - finding memory leaks in golang program - reflect.Value.call meaning 如何使用带有nil输入的reflect.Value.Call()? - How can I use reflect.Value.Call() with a nil input? 恐慌:反映:对 GORM .Create() 上的零值调用 reflect.Value.Interface - panic: reflect: call of reflect.Value.Interface on zero Value on GORM .Create() 恐慌:反映:在接口值上调用 reflect.Value.FieldByName - panic: reflect: call of reflect.Value.FieldByName on interface Value rpc sendResponse panic:reflect:在ptr上调用reflect.Value.Int - rpc sendResponse panic:reflect: call of reflect.Value.Int on ptr 反映运行时错误:在零值上调用reflect.flag.mustBeAssignable - reflect runtime error: call of reflect.flag.mustBeAssignable on zero Value Aerospike Golang客户端的putObject方法使我感到恐慌:反射:调用map Value上的reflect.Value.Elem - Aerospike Golang client putObject method gives me panic: reflect: call of reflect.Value.Elem on map Value 无法使用 GORM 将记录批量插入到 MSSQL 数据库中:reflect: call of reflect.Value.Interface on zero Value - Unable to batch insert records into MSSQL DB using GORM: reflect: call of reflect.Value.Interface on zero Value 反射:调用ptr Value上的reflect.Value.Field - reflect: call of reflect.Value.Field on ptr Value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM