diff --git a/27-reflection/reflection/main.go b/27-reflection/reflection/main.go index a052161..22648ba 100644 --- a/27-reflection/reflection/main.go +++ b/27-reflection/reflection/main.go @@ -29,4 +29,6 @@ func main() { main28() main29() main30() + main31() + main32() } diff --git a/27-reflection/reflection/re3.go b/27-reflection/reflection/re3.go index 309ae4a..7560200 100644 --- a/27-reflection/reflection/re3.go +++ b/27-reflection/reflection/re3.go @@ -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() +}