2016-06-15 2 views
-1

nahm ich ein Beispiel reflect.Select aus: https://www.socketloop.com/references/golang-reflect-select-and-selectcase-function-exampleWie chan Wert von einer Schnittstelle zu bekommen und es verwenden, in reflect.Select (...)

Es funktioniert so weit wie es geht. Aber es war das Erstellen des reflect.Value() von einem einfachen "chan": = make (chan int) Setup.

Aber ich wollte einen Kanal aus einer Struktur als Schnittstelle übergeben {}.

Also habe ich das Programm modifiziert, um eine Struktur zu erstellen und es an die Verarbeitung als einen Schnittstellenparameter übergeben.

laufen Wenn ich: Panik: reflektieren: Aufruf von reflect.Value.Elem auf struct Valuepanic: reflektieren: Aufruf von reflect.Value.Elem auf struct Wert

Das ist seltsam, weil ich die genauen Code ein anderes Programm, das funktioniert !!

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 
} 

Kann jeder Körper mir sagen, wo ich versuche, werde falsch, den Interface-Code zu verwenden in der einfachen Variablen Version ersetzen.

Das Programm ist unten mit Kommentaren zeigen Änderungen:

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

die Fehlermeldung hat erzählt. –

Antwort

1

Eine Möglichkeit, dies zu tun, ist die Reflexion nicht zu tun, sondern Typ Behauptung zu tun. So könnte man sagen:

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

Alternativ, wenn Sie darauf bestehen, reflect verwenden (das ist eine minderwertige Lösung hier), könnten Sie bekommen, was Sie durch Fallenlassen Elem() wollen. Zum Beispiel:

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

Oder sogar val.Field(0), wenn Sie den Namen nicht verwenden möchten. Auch hier ist die Typ-Assertion-Methode besser.

+0

Ich bekomme "undefined: Foo". Ich verstehe das Konzept, aber es muss eine – Godfather

+0

Grund dafür sein, dass es nicht funktioniert. Die Verwendung des Reflektionsbeispiels funktionierte gut und alles, was ich tat, war, den Reflection-Code durch den Type-Assertion-Code zu ersetzen, wie Sie es vorgeschlagen hatten. Irgendwelche Hinweise - Hast du dein Update getestet? Warum sieht es Foo nicht? – Godfather

+0

@Godfather In Ihrem Beispiel ist Foo in einer Funktion, außerhalb nicht sichtbar. Versuchen Sie, es aus der Funktion zu entfernen. Dann lese Effektives Go :) – cnicutar

Verwandte Themen