2017-02-02 8 views
0

私はリフレクションを使用して、ユーザー入力に基づいて動的な関数呼び出しを作成しようとしています。このコマンドはpanic:reflect:reflection ofValue.Call on zeroの値

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

どのように見えるかです

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

:私はそのようなようなユーザ入力を収集していますプログラムを起動すると、プロンプトが表示され、 "Hello"というコマンドを "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 

がどのように私はこの問題を解決することができますか?また、何が起こっていますか?

答えて

2

が使用する前に返品するものを確認したい場合があります。

反射でエクスポートされない関数が表示されないため、この場合はゼロの値が得られます。 helloは小文字で始まり、したがってエクスポートされません。

また、あまりにも多くのポインタをここで作成している、あなたはreflect.ValueOf(c)を行う必要があると思う。あなたは同時に多くのことをやって、デバッグしています。簡単な動作例を作り、そこからデバッグを続けてください。

これが私の作品:https://play.golang.org/p/Yd-WDRzura

+0

私のコードに更新されます。こんにちは、こんにちはに変更することで運がない。注:私はまた、それをハードコーディングして "Hello"を直接呼び出そうとしました。私はそのような入力変数を置き換えようと試みました: 'inputs:= [] reflect.Value {}'そして、Helloにはどんなパラメータも期待していませんでした。 – Parris

+1

@パリス私の答えを更新しました。このサイトの人々がシンプルでテスト可能な自己完結型のサンプルを要求するのは、同時に多くの問題をデバッグすることを避けるためです。おそらく、コード内にさらに多くの問題があります。テスト可能ではないので実際には分かりません。 – Art

+1

さて、私の答えは、 "あなたはポインタを必要としないもののためにその場でポインタを使用しています"でした。この場合、孤立したものが働いたので、完全な例を示すことは役に立ちました。私は新しいです、私は私が知らないものを知らない。 – Parris

1

はちょうどあなたのコード内の2つの変更を行います。 まず変更reflect.ValueOfにreflect.ValueOf(& C)(C) は、第二reflect.ValueOf(*コマンド)にreflect.ValueOf(コマンド)を変更

これはコードworkingcode