Files
yanzuoguang f98d6801b8 feat(go): 添加反射和通道相关功能
- 新增 main31 和 main32 函数入口
- 实现接口实现检查函数 checkImplementation
- 添加结构体包装器 Wrapper 及其字段反射方法 getUnderlying- 实现通道类型检查与数据发送功能
- 添加通道选择器 readChannels 支持多通道读取
- 创建测试函数 testChannelRead 和 testChannelRead1 验证通道操作
2025-11-02 10:09:27 +08:00

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