feat(go): 添加反射和通道相关功能

- 新增 main31 和 main32 函数入口
- 实现接口实现检查函数 checkImplementation
- 添加结构体包装器 Wrapper 及其字段反射方法 getUnderlying- 实现通道类型检查与数据发送功能
- 添加通道选择器 readChannels 支持多通道读取
- 创建测试函数 testChannelRead 和 testChannelRead1 验证通道操作
This commit is contained in:
2025-11-02 10:09:27 +08:00
parent e278aa30a7
commit f98d6801b8
2 changed files with 166 additions and 0 deletions

View File

@@ -29,4 +29,6 @@ func main() {
main28()
main29()
main30()
main31()
main32()
}

View File

@@ -198,6 +198,7 @@ func executeFirstVoidMethod1(s interface{}) {
}
}
}
func main30() {
Printfln("\nmain30:")
@@ -210,3 +211,166 @@ func main30() {
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()
}