簡體   English   中英

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

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

我正在嘗試使用反射來根據用戶輸入進行動態 function 調用。 我正在收集這樣的用戶輸入:

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

這就是命令被解析出來的方式

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

commands.go 文件如下所示

type Command struct {
    Name string
    Args []string
}

type Commander struct {}

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

當我運行該程序時,我得到一個提示,然后我運行一個名為“Hello”的命令和一個名為“world”的參數。 我希望出現“Meow [World]”或類似的東西。 像這樣:

> Hello world
Meow world

相反,我得到的是一個看起來像這樣的恐慌:

> 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

我怎樣才能解決這個問題? 另外,這是怎么回事?

您可能想在使用之前檢查reflect.ValueOf返回的內容。

在這種情況下,您將獲得一個 nil 值,因為reflect 看不到未導出的函數。 hello以小寫字母開頭,因此不會導出。

另外,你在這里提出了太多的指針,我懷疑你需要做reflect.ValueOf(c) 您同時在做和調試太多的事情。 制作一個簡單的工作示例並從那里繼續調試。

這對我有用https : //play.golang.org/p/Yd-WDRzura

只需在您的代碼中做兩個更改。 首先將reflect.ValueOf(&c) 更改為reflect.ValueOf(c) 其次將reflect.ValueOf(command) 更改為reflect.ValueOf(*command)

這是代碼workingcode

調用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM