- 新增 main31 和 main32 函数入口 - 实现接口实现检查函数 checkImplementation - 添加结构体包装器 Wrapper 及其字段反射方法 getUnderlying- 实现通道类型检查与数据发送功能 - 添加通道选择器 readChannels 支持多通道读取 - 创建测试函数 testChannelRead 和 testChannelRead1 验证通道操作
377 lines
10 KiB
Go
377 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func inspectFuncType(f interface{}) {
|
|
Printfln("\ninspectFuncType:")
|
|
funcType := reflect.TypeOf(f)
|
|
if funcType.Kind() != reflect.Func {
|
|
Printfln("Not a function")
|
|
return
|
|
}
|
|
Printfln("Function parameters count: %v", funcType.NumIn())
|
|
for i := 0; i < funcType.NumIn(); i++ {
|
|
paramType := funcType.In(i)
|
|
if i < funcType.NumIn()-1 {
|
|
Printfln("Parameter #%v, Type: %v", i, paramType)
|
|
} else {
|
|
Printfln("Parameter #%v, Type: %v, Variadic: %v", i, paramType, funcType.IsVariadic())
|
|
}
|
|
}
|
|
|
|
Printfln("Function results count: %v", funcType.NumOut())
|
|
for i := 0; i < funcType.NumOut(); i++ {
|
|
resultType := funcType.Out(i)
|
|
Printfln("Result #%v, Type: %v", i, resultType)
|
|
}
|
|
}
|
|
|
|
func invokeFunction(f interface{}, params ...interface{}) {
|
|
Printfln("\ninvokeFunction:")
|
|
paramVals := []reflect.Value{}
|
|
for _, p := range params {
|
|
paramVals = append(paramVals, reflect.ValueOf(p))
|
|
}
|
|
funcVal := reflect.ValueOf(f)
|
|
if funcVal.Kind() == reflect.Func {
|
|
results := funcVal.Call(paramVals)
|
|
for i, result := range results {
|
|
Printfln("Result #%v: %v", i, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func mapSlice(slice interface{}, mapper interface{}) (mapped []interface{}) {
|
|
Printfln("\nmapSlice:")
|
|
sliceVal := reflect.ValueOf(slice)
|
|
mapperVal := reflect.ValueOf(mapper)
|
|
mapped = []interface{}{}
|
|
if sliceVal.Kind() == reflect.Slice &&
|
|
mapperVal.Kind() == reflect.Func &&
|
|
mapperVal.Type().NumIn() == 1 &&
|
|
// 函数参数0的参数类型等于数组元素的参数类型
|
|
mapperVal.Type().In(0) == sliceVal.Type().Elem() {
|
|
for i := 0; i < sliceVal.Len(); i++ {
|
|
result := mapperVal.Call([]reflect.Value{sliceVal.Index(i)})
|
|
for _, r := range result {
|
|
mapped = append(mapped, r.Interface())
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func mapSlice1(slice interface{}, mapper interface{}) (mapped []interface{}) {
|
|
Printfln("\nmapSlice1:")
|
|
sliceVal := reflect.ValueOf(slice)
|
|
mapperVal := reflect.ValueOf(mapper)
|
|
mapped = []interface{}{}
|
|
if sliceVal.Kind() == reflect.Slice && mapperVal.Kind() == reflect.Func {
|
|
// 输入参数类型
|
|
paramTypes := []reflect.Type{sliceVal.Type().Elem()}
|
|
// 获取返回的结果集合类型
|
|
resultTypes := []reflect.Type{}
|
|
for i := 0; i < mapperVal.Type().NumOut(); i++ {
|
|
resultTypes = append(resultTypes, mapperVal.Type().Out(i))
|
|
}
|
|
// 创建一个函数类型
|
|
expectedFUncType := reflect.FuncOf(paramTypes, resultTypes, mapperVal.Type().IsVariadic())
|
|
|
|
if mapperVal.Type() == expectedFUncType {
|
|
for i := 0; i < sliceVal.Len(); i++ {
|
|
result := mapperVal.Call([]reflect.Value{sliceVal.Index(i)})
|
|
for _, r := range result {
|
|
mapped = append(mapped, r.Interface())
|
|
}
|
|
}
|
|
} else {
|
|
Printfln("Function type not as expected")
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func main28() {
|
|
Printfln("\nmain28:")
|
|
|
|
inspectFuncType(Find)
|
|
|
|
names := []string{"Alice", "Bob", "Charlie"}
|
|
invokeFunction(Find, names, "London", "Bob")
|
|
|
|
results := mapSlice(names, strings.ToUpper)
|
|
Printfln("Results: %v", results)
|
|
|
|
results = mapSlice1(names, strings.ToUpper)
|
|
Printfln("Results: %v", results)
|
|
}
|
|
|
|
func makeMapperFunc(mapper interface{}) interface{} {
|
|
Printfln("\nmakeMapperFunc:")
|
|
mapVal := reflect.ValueOf(mapper)
|
|
mapType := mapVal.Type()
|
|
if mapVal.Kind() == reflect.Func && mapType.NumIn() == 1 && mapType.NumOut() == 1 {
|
|
inType := reflect.SliceOf(mapType.In(0))
|
|
inTypeSlice := []reflect.Type{inType}
|
|
outType := reflect.SliceOf(mapType.Out(0))
|
|
outTypeSlice := []reflect.Type{outType}
|
|
funcType := reflect.FuncOf(inTypeSlice, outTypeSlice, false)
|
|
funcVal := reflect.MakeFunc(funcType, func(params []reflect.Value) (results []reflect.Value) {
|
|
srcSliceVal := params[0]
|
|
resultsSliceVal := reflect.MakeSlice(outType, srcSliceVal.Len(), srcSliceVal.Len())
|
|
for i := 0; i < srcSliceVal.Len(); i++ {
|
|
r := mapVal.Call([]reflect.Value{srcSliceVal.Index(i)})
|
|
resultsSliceVal.Index(i).Set(r[0])
|
|
}
|
|
results = []reflect.Value{resultsSliceVal}
|
|
return
|
|
})
|
|
return funcVal.Interface()
|
|
}
|
|
Printfln("Unexpected types")
|
|
return nil
|
|
}
|
|
|
|
func main29() {
|
|
Printfln("\nmain29:")
|
|
|
|
lowerStringMapper := makeMapperFunc(strings.ToLower).(func([]string) []string)
|
|
names := []string{"Alice", "Bob", "Charlie"}
|
|
Printfln("Results: %v", lowerStringMapper(names))
|
|
|
|
incrementFloatMapper := makeMapperFunc(func(val float64) float64 {
|
|
return val + 1
|
|
}).(func([]float64) []float64)
|
|
prices := []float64{279, 48.95, 19.50}
|
|
Printfln("Results: %v", incrementFloatMapper(prices))
|
|
|
|
floatToStringMapper := makeMapperFunc(func(val float64) string {
|
|
return fmt.Sprintf("$%.2f", val)
|
|
}).(func([]float64) []string)
|
|
Printfln("Results: %v", floatToStringMapper(prices))
|
|
}
|
|
|
|
func inspectMethods(s interface{}) {
|
|
sType := reflect.TypeOf(s)
|
|
if sType.Kind() == reflect.Struct ||
|
|
(sType.Kind() == reflect.Ptr && sType.Elem().Kind() == reflect.Struct) {
|
|
Printfln("Type : %v,Methods: %v", sType, sType.NumMethod())
|
|
for i := 0; i < sType.NumMethod(); i++ {
|
|
method := sType.Method(i)
|
|
Printfln("Method #%v Name: %v, Type: %v", i, method.Name, method.Type)
|
|
}
|
|
}
|
|
}
|
|
|
|
func executeFirstVoidMethod(s interface{}) {
|
|
Printfln("\nexecuteFirstVoidMethod:")
|
|
sVal := reflect.ValueOf(s)
|
|
for i := 0; i < sVal.NumMethod(); i++ {
|
|
method := sVal.Type().Method(i)
|
|
if method.Type.NumIn() == 1 {
|
|
results := method.Func.Call([]reflect.Value{sVal})
|
|
Printfln("Type %v, Method %v, Result: %v", sVal.Type(), method.Name, results)
|
|
break
|
|
} else {
|
|
Printfln("Skipping method %v %v", method.Name, method.Type.NumIn())
|
|
}
|
|
}
|
|
}
|
|
|
|
func executeFirstVoidMethod1(s interface{}) {
|
|
Printfln("\nexecuteFirstVoidMethod1:")
|
|
sVal := reflect.ValueOf(s)
|
|
for i := 0; i < sVal.NumMethod(); i++ {
|
|
method := sVal.Method(i)
|
|
// 这里 method为 指针
|
|
if method.Type().NumIn() == 0 {
|
|
results := method.Call([]reflect.Value{})
|
|
Printfln("Type %v, Method %v, Result: %v", sVal.Type(), sVal.Type().Method(i).Name, results)
|
|
// Printfln("Type %v, Method %v, Result: %v", sVal.Type(), method.Type().Elem().Name, results)
|
|
break
|
|
} else {
|
|
Printfln("Skipping method %v %v", sVal.Type().Method(i).Name, method.Type().NumIn())
|
|
}
|
|
}
|
|
}
|
|
|
|
func main30() {
|
|
Printfln("\nmain30:")
|
|
|
|
inspectMethods(Product{})
|
|
inspectMethods(&Product{})
|
|
|
|
inspectMethods(Purchase{})
|
|
inspectMethods(&Purchase{})
|
|
|
|
executeFirstVoidMethod(&Product{Name: "Kayak", Price: 279})
|
|
executeFirstVoidMethod1(&Product{Name: "Kayak", Price: 279})
|
|
}
|
|
|
|
func checkImplementation(check interface{}, targets ...interface{}) {
|
|
checkType := reflect.TypeOf(check)
|
|
if checkType.Kind() == reflect.Ptr && checkType.Elem().Kind() == reflect.Interface {
|
|
checkType = checkType.Elem()
|
|
for _, target := range targets {
|
|
targetType := reflect.TypeOf(target)
|
|
Printfln("Type: %v implements %v : %v", targetType, checkType, targetType.Implements(checkType))
|
|
}
|
|
}
|
|
}
|
|
|
|
type Wrapper struct {
|
|
NamedItem
|
|
}
|
|
|
|
// 获取接口定义字段的实现类
|
|
func getUnderlying(item Wrapper, fieldName string) {
|
|
itemVal := reflect.ValueOf(item)
|
|
fieldVal := itemVal.FieldByName(fieldName)
|
|
fieldType := fieldVal.Type()
|
|
Printfln("Field Type: %v ", fieldType)
|
|
|
|
for i := 0; i < fieldType.NumMethod(); i++ {
|
|
method := fieldType.Method(i)
|
|
Printfln("Interface Method: %v, PkgPath: %v, ", method.Name, method.PkgPath)
|
|
}
|
|
|
|
Printfln("-----------")
|
|
if fieldVal.Kind() == reflect.Interface {
|
|
fieldElem := fieldVal.Elem()
|
|
fieldElemType := fieldElem.Type()
|
|
Printfln("Underlying Type: %v", fieldElemType)
|
|
|
|
for i := 0; i < fieldElemType.NumMethod(); i++ {
|
|
method := fieldElemType.Method(i)
|
|
Printfln("Underlying Method: %v, PkgPath: %v, ", method.Name, method.PkgPath)
|
|
}
|
|
}
|
|
}
|
|
|
|
func main31() {
|
|
Printfln("\nmain31:")
|
|
|
|
currencyItemType := (*CurrencyItem)(nil)
|
|
checkImplementation(currencyItemType, Product{}, &Product{}, &Purchase{})
|
|
|
|
getUnderlying(Wrapper{NamedItem: &Product{}}, "NamedItem")
|
|
}
|
|
|
|
func inspectChannel(channel interface{}) {
|
|
Printfln("\ninspectChannel:")
|
|
channelType := reflect.TypeOf(channel)
|
|
if channelType.Kind() == reflect.Chan {
|
|
Printfln("Channel Type: %v, Direction: %v", channelType, channelType.ChanDir())
|
|
}
|
|
}
|
|
|
|
func sendOverChannel(channel interface{}, data interface{}) {
|
|
Printfln("\nsendToChannel:")
|
|
channelVal := reflect.ValueOf(channel)
|
|
dataVal := reflect.ValueOf(data)
|
|
if channelVal.Kind() == reflect.Chan && dataVal.Kind() == reflect.Slice && channelVal.Type().Elem() == dataVal.Type().Elem() {
|
|
for i := 0; i < dataVal.Len(); i++ {
|
|
val := dataVal.Index(i)
|
|
channelVal.Send(val)
|
|
}
|
|
channelVal.Close()
|
|
} else {
|
|
Printfln("Unexpected types: %v , %v ", channelVal.Type(), dataVal.Type())
|
|
}
|
|
}
|
|
|
|
func createChannelAndSend(data interface{}) interface{} {
|
|
Printfln("\ncreateChannelAndSend:")
|
|
dataVal := reflect.ValueOf(data)
|
|
channelType := reflect.ChanOf(reflect.BothDir, dataVal.Type().Elem())
|
|
channel := reflect.MakeChan(channelType, 1)
|
|
go func() {
|
|
if dataVal.Kind() == reflect.Slice {
|
|
for i := 0; i < dataVal.Len(); i++ {
|
|
channel.Send(dataVal.Index(i))
|
|
}
|
|
} else {
|
|
Printfln("data not Slice types: %v ", dataVal.Type())
|
|
}
|
|
channel.Close()
|
|
}()
|
|
return channel.Interface()
|
|
}
|
|
|
|
func DisplayChan(channel chan string) {
|
|
for {
|
|
if val, open := <-channel; open {
|
|
Printfln("Received value: %v", val)
|
|
} else {
|
|
Printfln("Channel closed")
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
func readChannels(channels ...interface{}) {
|
|
channelsVal := reflect.ValueOf(channels)
|
|
cases := []reflect.SelectCase{}
|
|
for i := 0; i < channelsVal.Len(); i++ {
|
|
cases = append(cases, reflect.SelectCase{
|
|
Dir: reflect.SelectRecv,
|
|
Chan: channelsVal.Index(i).Elem(),
|
|
})
|
|
}
|
|
for {
|
|
caseIndex, val, ok := reflect.Select(cases)
|
|
if ok {
|
|
Printfln("Index %v Value Read: %v Type: %v from channel %v", caseIndex, val, val.Type())
|
|
} else {
|
|
if len(cases) == 1 {
|
|
Printfln("All Channel closed")
|
|
return
|
|
}
|
|
// 将当前通道删除,从而避免下次Select的时候重复处理
|
|
cases = append(cases[:caseIndex], cases[caseIndex+1:]...)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testChannelRead() {
|
|
Printfln("\ntestChannelRead:")
|
|
var c chan<- string
|
|
inspectChannel(c)
|
|
|
|
values := []string{"Alice", "Bob", "Charlie", "Dora"}
|
|
channel := make(chan string)
|
|
go sendOverChannel(channel, values)
|
|
DisplayChan(channel)
|
|
|
|
channel = createChannelAndSend(values).(chan string)
|
|
DisplayChan(channel)
|
|
}
|
|
|
|
func testChannelRead1() {
|
|
Printfln("\ntestChannelRead1:")
|
|
|
|
values := []string{"Alice", "Bob", "Charlie", "Dora"}
|
|
channel := createChannelAndSend(values).(chan string)
|
|
|
|
cities := []string{"London", "Rome", "Paris"}
|
|
cityChannel := createChannelAndSend(cities).(chan string)
|
|
|
|
prices := []float64{279, 48.95, 19.50}
|
|
priceChannel := createChannelAndSend(prices).(chan float64)
|
|
|
|
readChannels(channel, cityChannel, priceChannel)
|
|
|
|
}
|
|
|
|
func main32() {
|
|
Printfln("\nmain32:")
|
|
|
|
testChannelRead()
|
|
|
|
testChannelRead1()
|
|
}
|