2016-06-15 5 views
-1

でそれを使用するために、私はからreflect.Selectの例を取りました。しかし、それは単純な "chan"からreflect.Value()を作成していました:= make(chan int)setup。どのインターフェースからちゃん値を取得し、reflect.Select(...)

しかし、インタフェース{}として渡された構造体のチャネルを使用したかったのです。

私は構造体を作成し、それを処理のためにインターフェイスパラメータ として渡すようにプログラムを修正しました。

実行すると、私が手:パニック:反映します。struct Valuepanic上reflect.Value.Elemの呼び出し:反映します。struct値にreflect.Value.Elemの呼び出しを

これは奇妙であるI正確なコード理由動作する別のプログラム!

func inspect(f interface{}) map[string]string { 

    m := make(map[string]string) 
    val := reflect.ValueOf(f).Elem() 

    for i := 0; i < val.NumField(); i++ { 
     valueField := val.Field(i) 
     typeField := val.Type().Field(i) 
     f := valueField.Interface() 

     val := reflect.ValueOf(f) 
     m[typeField.Name] = val.String() 
    } 

    return m 
} 

いかなる 体は、私は単純な変数バージョンで置き換えるには、インタフェースコード を使用しようとして間違ったつもりどこを教えてもらえます。

プログラムは、変化を示すコメントを以下の通りです:これを行うには

package main 

// Original Example from: 
// https://www.socketloop.com/references/golang-reflect-select-and-selectcase-function-example 
// 
import (
    "fmt" 
    "reflect" 
) 

func main() { 

    // following replaces " var sendCh := make(chan int) " 
    type Foo struct { 
     Ch chan int 
    } 
    sendCh := Foo{make(chan int)} 
    // End of replacement code 

    var increaseInt = func(c chan int) { 
     for i := 0; i < 8; i++ { 
      c <- i 
     } 
     close(c) 
    } 

    go increaseInt(sendCh.Ch) 

    // This routine call replaces the code incorporated in "runJob" 
    // It was done so I could call through an empty interface{} 
    runJob(sendCh) 
    // End replaement code-- 
} 

func runJob(f interface{}) { 
    var selectCase = make([]reflect.SelectCase, 1) 

    // This code replaces just using the orginal "sendCh" value 
    // I am trying here to construct "sendCh" from the interface value 
    val := reflect.ValueOf(f).Elem() 
    valueField := val.Field(0) 
    sendCh := valueField.Interface() 
    // End of replacement code 

    selectCase[0].Dir = reflect.SelectRecv 
    selectCase[0].Chan = reflect.ValueOf(sendCh) 

    counter := 0 
    for counter < 1 { 
     chosen, recv, recvOk := reflect.Select(selectCase) // <--- here 
     if recvOk { 
      fmt.Println(chosen, recv.Int(), recvOk) 

     } else { 
      fmt.Println("Exit Condition Detected: ", chosen, recv.Int(), recvOk) 
      counter++ 
     } 
    } 
} 
+1

エラーメッセージが伝えました。 –

答えて

1

一つの方法は、リフレクションを行う代わりに、型アサーションをしないことです。だからあなたが言うことができる:

また
val, ok := f.(Foo) 
if !ok { 
    fmt.Printf("Not Foo? Try Bar.\n") 
} 
sendCh := val.Ch 

、あなたは(ここで劣るソリューションである)reflectを使う、という場合は、Elem()をドロップすることにより、あなたが欲しいものを得ることができます。たとえば、

val := reflect.ValueOf(f) 
valueField := val.FieldByName("Ch") 
sendCh := valueField.Interface() 

さらには名前を使用しない場合はval.Field(0)となります。この場合も、型アサーションの方法がこれより優れています。

+0

私は "undefined:Foo"を取得します。私はそのコンセプトを理解していますが、それはうまくいかない理由が – Godfather

+0

である必要があります。リフレクションの例を使用するとうまくいきました。あなたが示唆したようにリフレクションコードをタイプアサーションコードに置き換えていました。すべての手がかり - あなたの修正をテストしましたか?なぜFooが見えないのですか? – Godfather

+0

@ Godfatherあなたの例では、Fooは関数内にあり、外部には表示されません。関数から移動してみてください。その後、有効な読書を試してください:) – cnicutar

関連する問題