我举了一个反映的例子。选自: 的 https://www.socketloop.com/references/golang-reflect-select-and-selectcase-function-example
它尽可能地发挥作用。但它是从一个简单的创建reflect.Value() " CHAN" := make(chan int)设置。
但我想使用来自作为接口{}传递的结构的通道。
所以我修改了程序来创建一个结构并将其传递给处理 接口参数。
运行时,我得到:恐慌:反映:关于struct的调用.Value.Elem。值得反映:对结构值调用reflect.Value.Elem
这很奇怪,因为我确切的代码是另一个有效的程序!!
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++
}
}
}
答案 0 :(得分: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)
。同样,类型断言方法比这更好。