feat(go): 添加反射和通道相关功能
- 新增 main31 和 main32 函数入口 - 实现接口实现检查函数 checkImplementation - 添加结构体包装器 Wrapper 及其字段反射方法 getUnderlying- 实现通道类型检查与数据发送功能 - 添加通道选择器 readChannels 支持多通道读取 - 创建测试函数 testChannelRead 和 testChannelRead1 验证通道操作
This commit is contained in:
@@ -29,4 +29,6 @@ func main() {
|
||||
main28()
|
||||
main29()
|
||||
main30()
|
||||
main31()
|
||||
main32()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user