diff --git a/27-reflection/reflection/main.go b/27-reflection/reflection/main.go index 83adf5d..3db8ece 100644 --- a/27-reflection/reflection/main.go +++ b/27-reflection/reflection/main.go @@ -1,274 +1,8 @@ package main -import ( - "fmt" - "reflect" - "strings" -) - -type Payment struct { - Currency string - Amount float64 -} - -func printDetails(values ...Product) { - for _, elem := range values { - Printfln("Name: %v, Category: %v, Price: %v", elem.Name, elem.Category, elem.Price) - } -} -func printDetails1(values ...interface{}) { - Printfln("\nprintDetails1:") - for _, elem := range values { - switch val := elem.(type) { - case Product: - Printfln("Name: %v, Category: %v, Price: %v", val.Name, val.Category, val.Price) - case Customer: - Printfln("Name: %v, City: %v", val.Name, val.City) - } - } -} - -func printDetails2(values ...interface{}) { - Printfln("\nprintDetails2:") - for _, elem := range values { - fieldDetails := []string{} - elemType := reflect.TypeOf(elem) - elemValue := reflect.ValueOf(elem) - if elemType.Kind() == reflect.Struct { - for i := 0; i < elemType.NumField(); i++ { - field := elemType.Field(i) - fieldVal := elemValue.Field(i) - fieldDetails = append(fieldDetails, fmt.Sprintf("%v: %v", field.Name, fieldVal)) - } - Printfln("%v: %v", elemType.Name(), strings.Join(fieldDetails, ", ")) - } else { - Printfln("%v: %v", elemType.Name(), elemValue) - } - - } -} - -func printDetails3(values ...interface{}) { - Printfln("\nprintDetails3:") - for _, elem := range values { - elemType := reflect.TypeOf(elem) - Printfln("Name: %v ,PkgPath: %v , Kind: %v", elemType.Name(), getTypePath3(elemType), elemType.Kind()) - } -} - -func getTypePath3(elemType reflect.Type) interface{} { - path := elemType.PkgPath() - if path == "" { - return "(built-in)" - } - return path -} - -func printType(elemValue *reflect.Value) { - switch elemValue.Kind() { - case reflect.Bool: - Printfln("Bool: %v", elemValue.Bool()) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - Printfln("Int: %v", elemValue.Int()) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - Printfln("Uint: %v", elemValue.Uint()) - case reflect.Float32, reflect.Float64: - Printfln("Float: %v", elemValue.Float()) - case reflect.String: - Printfln("String: %v", elemValue.String()) - case reflect.Ptr: - var val = elemValue.Elem() - if val.Kind() == reflect.Int { - Printfln("Pointer to Int: %v", val.Int()) - } - case reflect.Struct: - Printfln("Struct type: %v string: %v", elemValue.Type(), elemValue.String()) - default: - Printfln("Unsupported type: %v string: %v", elemValue.Type(), elemValue.String()) - - } -} - -func printDetails4(values ...interface{}) { - Printfln("\nprintDetails4:") - for _, elem := range values { - elemValue := reflect.ValueOf(elem) - printType(&elemValue) - } -} - -var intPtrType = reflect.TypeOf((*int)(nil)) -var byteSliceType = reflect.TypeOf([]byte(nil)) - -func printDetails5(values ...interface{}) { - Printfln("\nprintDetails5:") - for _, elem := range values { - elemValue := reflect.ValueOf(elem) - elemType := reflect.TypeOf(elem) - if elemType == intPtrType { - Printfln("Type Pointer to Int: %v", elemValue.Elem().Int()) - continue - } else if elemType == byteSliceType { - Printfln("Type Byte slice: %v", elemValue.Bytes()) - continue - } - - printType(&elemValue) - } -} - -func selectValue6(data interface{}, index int) (result interface{}) { - Printfln("\nselectValue6:") - dataVal := reflect.ValueOf(data) - if dataVal.Kind() == reflect.Array || dataVal.Kind() == reflect.Slice { - result = dataVal.Index(index).Interface() - } - return -} - -func incrementOrUpper7(values ...interface{}) { - Printfln("\nincrementOrUpper7:") - for _, elem := range values { - elemValue := reflect.ValueOf(elem) - if elemValue.Kind() == reflect.Ptr { - elemValue = elemValue.Elem() - } - if elemValue.CanSet() { - switch elemValue.Kind() { - case reflect.String: - elemValue.SetString(strings.ToUpper(elemValue.String())) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - elemValue.SetInt(elemValue.Int() + 1) - default: - Printfln("unhandled default case") - } - Printfln("Modified Value: %v", elemValue) - } else { - Printfln("Cannot set %v: %v", elemValue.Kind(), elemValue) - } - } -} - -func setAll9(src interface{}, targets ...interface{}) { - srcVal := reflect.ValueOf(src) - for _, target := range targets { - targetVal := reflect.ValueOf(target) - if targetVal.Kind() == reflect.Ptr { - targetVal = targetVal.Elem() - } - if targetVal.CanSet() && targetVal.Type() == srcVal.Type() { - targetVal.Set(srcVal) - } - } -} - -func contains(slice interface{}, target interface{}) (found bool) { - sliceVal := reflect.ValueOf(slice) - targetType := reflect.TypeOf(target) - if sliceVal.Kind() == reflect.Slice && sliceVal.Type().Elem().Comparable() && targetType.Comparable() { - for i := 0; i < sliceVal.Len(); i++ { - if sliceVal.Index(i).Interface() == target { - found = true - break - } - } - } - return -} - -func contains11(slice interface{}, target interface{}) (found bool) { - sliceVal := reflect.ValueOf(slice) - if sliceVal.Kind() == reflect.Slice { - for i := 0; i < sliceVal.Len(); i++ { - if reflect.DeepEqual(sliceVal.Index(i).Interface(), target) { - found = true - break - } - } - } - return -} - -func convert12(src, target interface{}) (result interface{}, assigned bool) { - srcVal := reflect.ValueOf(src) - targetVal := reflect.ValueOf(target) - if srcVal.Type().ConvertibleTo(targetVal.Type()) { - result = srcVal.Convert(targetVal.Type()).Interface() - assigned = true - } else { - result = src - } - return -} - -func IsInt(v reflect.Value) bool { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return true - } - return false -} -func IsFloat(v reflect.Value) bool { - switch v.Kind() { - case reflect.Float32, reflect.Float64: - return true - } - return false -} - -func convert13(src, target interface{}) (result interface{}, assigned bool) { - srcVal := reflect.ValueOf(src) - targetVal := reflect.ValueOf(target) - if srcVal.Type().ConvertibleTo(targetVal.Type()) { - if IsInt(targetVal) && IsInt(srcVal) && targetVal.OverflowInt(srcVal.Int()) { - Printfln("Int Overflow") - return src, false - } else if IsFloat(targetVal) && IsFloat(srcVal) && targetVal.OverflowFloat(srcVal.Float()) { - Printfln("Float Overflow") - return src, false - } - result = srcVal.Convert(targetVal.Type()).Interface() - assigned = true - } else { - result = src - } - return -} - -func swap(first, second interface{}) { - firstValue, secondValue := reflect.ValueOf(first), reflect.ValueOf(second) - if firstValue.Type() == secondValue.Type() && firstValue.Kind() == reflect.Ptr && firstValue.Elem().CanSet() && secondValue.Elem().CanSet() { - temp := reflect.New(firstValue.Elem().Type()) - temp.Elem().Set(firstValue.Elem()) - firstValue.Elem().Set(secondValue.Elem()) - secondValue.Elem().Set(temp.Elem()) - } -} - func main() { - product := Product{"Kayak", "Watersports", 279} - customer := Customer{"Alice", "New York"} - payment := Payment{"USD", 100.50} - - // printDetails(product, customer) - printDetails1(product, customer) - - printDetails2(product, customer, payment, 10, true) - - printDetails3(product, customer, payment, 10, true) - - number := 10 - printDetails4(true, 10, 23.30, "Alice", &number, product) - - printDetails5(true, 10, 23.30, "Alice", &number, product) - - slice := []byte("Alice") - printDetails5(true, 10, 23.30, "Alice", &number, product, slice) - - names := []string{"Alice", "Bob", "Charlie"} - val := selectValue6(names, 1).(string) - Printfln("Selected: %v", val) + main1_6() main7() main8() main9() @@ -278,98 +12,3 @@ func main() { main13() main14() } - -func main7() { - name := "Alice" - price := 279 - city := "London" - incrementOrUpper7(name, price, city) - for _, val := range []interface{}{name, price, city} { - Printfln("Value: %v", val) - } -} - -func main8() { - name := "Alice" - price := 279 - city := "London" - incrementOrUpper7(&name, &price, &city) - for _, val := range []interface{}{name, price, city} { - Printfln("Value: %v", val) - } -} - -func main9() { - Printfln("\nmain9:") - name := "Alice" - price := 279 - city := "London" - setAll9("New String", &name, &price, &city) - setAll9(10, &name, &price, &city) - for _, val := range []interface{}{name, price, city} { - Printfln("Value: %v", val) - } -} - -func main10() { - Printfln("\nmain10:") - - city := "London" - - citiesSlice := []string{"Paris", "Rome", "London"} - Printfln("Found #1: %v", contains(citiesSlice, city)) - - sliceOfSlices := [][]string{citiesSlice, {"First", "Second", "Third"}} - Printfln("Found #2: %v", contains(sliceOfSlices, citiesSlice)) -} - -func main11() { - Printfln("\nmain11:") - - city := "London" - - citiesSlice := []string{"Paris", "Rome", "London"} - Printfln("Found #1: %v", contains11(citiesSlice, city)) - - sliceOfSlices := [][]string{citiesSlice, {"First", "Second", "Third"}} - Printfln("Found #2: %v", contains11(sliceOfSlices, citiesSlice)) -} - -func main12() { - Printfln("\nmain12:") - name := "Alice" - price := 279 - - newVal, ok := convert12(price, 100.00) - Printfln("Converted %v: %v, %T", ok, newVal, newVal) - newVal, ok = convert12(name, 100.00) - Printfln("Converted %v: %v, %T", ok, newVal, newVal) -} - -func main13() { - Printfln("\nmain13:") - name := "Alice" - price := 279 - - newVal, ok := convert13(price, 100.00) - Printfln("Converted %v: %v, %T", ok, newVal, newVal) - newVal, ok = convert13(name, 100.00) - Printfln("Converted %v: %v, %T", ok, newVal, newVal) - - newVal, ok = convert13(5000, int8(100)) - Printfln("Converted %v: %v, %T", ok, newVal, newVal) - -} - -func main14() { - Printfln("\nmain14:") - name := "Alice" - price := 279 - city := "London" - swap(&name, &city) - - for _, val := range []interface{}{name, price, city} { - Printfln("Value: %v", val) - } - -} diff --git a/27-reflection/reflection/re1.go b/27-reflection/reflection/re1.go new file mode 100644 index 0000000..0d72821 --- /dev/null +++ b/27-reflection/reflection/re1.go @@ -0,0 +1,361 @@ +package main + +import ( + "fmt" + "reflect" + "strings" +) + +func printDetails(values ...Product) { + for _, elem := range values { + Printfln("Name: %v, Category: %v, Price: %v", elem.Name, elem.Category, elem.Price) + } +} +func printDetails1(values ...interface{}) { + Printfln("\nprintDetails1:") + for _, elem := range values { + switch val := elem.(type) { + case Product: + Printfln("Name: %v, Category: %v, Price: %v", val.Name, val.Category, val.Price) + case Customer: + Printfln("Name: %v, City: %v", val.Name, val.City) + } + } +} + +func printDetails2(values ...interface{}) { + Printfln("\nprintDetails2:") + for _, elem := range values { + fieldDetails := []string{} + elemType := reflect.TypeOf(elem) + elemValue := reflect.ValueOf(elem) + if elemType.Kind() == reflect.Struct { + for i := 0; i < elemType.NumField(); i++ { + field := elemType.Field(i) + fieldVal := elemValue.Field(i) + fieldDetails = append(fieldDetails, fmt.Sprintf("%v: %v", field.Name, fieldVal)) + } + Printfln("%v: %v", elemType.Name(), strings.Join(fieldDetails, ", ")) + } else { + Printfln("%v: %v", elemType.Name(), elemValue) + } + + } +} + +func printDetails3(values ...interface{}) { + Printfln("\nprintDetails3:") + for _, elem := range values { + elemType := reflect.TypeOf(elem) + Printfln("Name: %v ,PkgPath: %v , Kind: %v", elemType.Name(), getTypePath3(elemType), elemType.Kind()) + } +} + +func getTypePath3(elemType reflect.Type) interface{} { + path := elemType.PkgPath() + if path == "" { + return "(built-in)" + } + return path +} + +func printType(elemValue *reflect.Value) { + switch elemValue.Kind() { + case reflect.Bool: + Printfln("Bool: %v", elemValue.Bool()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + Printfln("Int: %v", elemValue.Int()) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + Printfln("Uint: %v", elemValue.Uint()) + case reflect.Float32, reflect.Float64: + Printfln("Float: %v", elemValue.Float()) + case reflect.String: + Printfln("String: %v", elemValue.String()) + case reflect.Ptr: + var val = elemValue.Elem() + if val.Kind() == reflect.Int { + Printfln("Pointer to Int: %v", val.Int()) + } + case reflect.Struct: + Printfln("Struct type: %v string: %v", elemValue.Type(), elemValue.String()) + default: + Printfln("Unsupported type: %v string: %v", elemValue.Type(), elemValue.String()) + + } +} + +func printDetails4(values ...interface{}) { + Printfln("\nprintDetails4:") + for _, elem := range values { + elemValue := reflect.ValueOf(elem) + printType(&elemValue) + } +} + +var intPtrType = reflect.TypeOf((*int)(nil)) +var byteSliceType = reflect.TypeOf([]byte(nil)) + +func printDetails5(values ...interface{}) { + Printfln("\nprintDetails5:") + for _, elem := range values { + elemValue := reflect.ValueOf(elem) + elemType := reflect.TypeOf(elem) + if elemType == intPtrType { + Printfln("Type Pointer to Int: %v", elemValue.Elem().Int()) + continue + } else if elemType == byteSliceType { + Printfln("Type Byte slice: %v", elemValue.Bytes()) + continue + } + + printType(&elemValue) + } +} + +func selectValue6(data interface{}, index int) (result interface{}) { + Printfln("\nselectValue6:") + dataVal := reflect.ValueOf(data) + if dataVal.Kind() == reflect.Array || dataVal.Kind() == reflect.Slice { + result = dataVal.Index(index).Interface() + } + return +} + +func incrementOrUpper7(values ...interface{}) { + Printfln("\nincrementOrUpper7:") + for _, elem := range values { + elemValue := reflect.ValueOf(elem) + if elemValue.Kind() == reflect.Ptr { + elemValue = elemValue.Elem() + } + if elemValue.CanSet() { + switch elemValue.Kind() { + case reflect.String: + elemValue.SetString(strings.ToUpper(elemValue.String())) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + elemValue.SetInt(elemValue.Int() + 1) + default: + Printfln("unhandled default case") + } + Printfln("Modified Value: %v", elemValue) + } else { + Printfln("Cannot set %v: %v", elemValue.Kind(), elemValue) + } + } +} + +func setAll9(src interface{}, targets ...interface{}) { + srcVal := reflect.ValueOf(src) + for _, target := range targets { + targetVal := reflect.ValueOf(target) + if targetVal.Kind() == reflect.Ptr { + targetVal = targetVal.Elem() + } + if targetVal.CanSet() && targetVal.Type() == srcVal.Type() { + targetVal.Set(srcVal) + } + } +} + +func contains(slice interface{}, target interface{}) (found bool) { + sliceVal := reflect.ValueOf(slice) + targetType := reflect.TypeOf(target) + if sliceVal.Kind() == reflect.Slice && sliceVal.Type().Elem().Comparable() && targetType.Comparable() { + for i := 0; i < sliceVal.Len(); i++ { + if sliceVal.Index(i).Interface() == target { + found = true + break + } + } + } + return +} + +func contains11(slice interface{}, target interface{}) (found bool) { + sliceVal := reflect.ValueOf(slice) + if sliceVal.Kind() == reflect.Slice { + for i := 0; i < sliceVal.Len(); i++ { + if reflect.DeepEqual(sliceVal.Index(i).Interface(), target) { + found = true + break + } + } + } + return +} + +func convert12(src, target interface{}) (result interface{}, assigned bool) { + srcVal := reflect.ValueOf(src) + targetVal := reflect.ValueOf(target) + if srcVal.Type().ConvertibleTo(targetVal.Type()) { + result = srcVal.Convert(targetVal.Type()).Interface() + assigned = true + } else { + result = src + } + return +} + +func IsInt(v reflect.Value) bool { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + } + return false +} +func IsFloat(v reflect.Value) bool { + switch v.Kind() { + case reflect.Float32, reflect.Float64: + return true + } + return false +} + +func convert13(src, target interface{}) (result interface{}, assigned bool) { + srcVal := reflect.ValueOf(src) + targetVal := reflect.ValueOf(target) + if srcVal.Type().ConvertibleTo(targetVal.Type()) { + if IsInt(targetVal) && IsInt(srcVal) && targetVal.OverflowInt(srcVal.Int()) { + Printfln("Int Overflow") + return src, false + } else if IsFloat(targetVal) && IsFloat(srcVal) && targetVal.OverflowFloat(srcVal.Float()) { + Printfln("Float Overflow") + return src, false + } + result = srcVal.Convert(targetVal.Type()).Interface() + assigned = true + } else { + result = src + } + return +} + +func swap(first, second interface{}) { + firstValue, secondValue := reflect.ValueOf(first), reflect.ValueOf(second) + if firstValue.Type() == secondValue.Type() && firstValue.Kind() == reflect.Ptr && firstValue.Elem().CanSet() && secondValue.Elem().CanSet() { + temp := reflect.New(firstValue.Elem().Type()) + temp.Elem().Set(firstValue.Elem()) + firstValue.Elem().Set(secondValue.Elem()) + secondValue.Elem().Set(temp.Elem()) + } +} + +func main1_6() { + product := Product{"Kayak", "Watersports", 279} + customer := Customer{"Alice", "New York"} + payment := Payment{"USD", 100.50} + + // printDetails(product, customer) + printDetails1(product, customer) + + printDetails2(product, customer, payment, 10, true) + + printDetails3(product, customer, payment, 10, true) + + number := 10 + printDetails4(true, 10, 23.30, "Alice", &number, product) + + printDetails5(true, 10, 23.30, "Alice", &number, product) + + slice := []byte("Alice") + printDetails5(true, 10, 23.30, "Alice", &number, product, slice) + + names := []string{"Alice", "Bob", "Charlie"} + val := selectValue6(names, 1).(string) + Printfln("Selected: %v", val) +} + +func main7() { + name := "Alice" + price := 279 + city := "London" + incrementOrUpper7(name, price, city) + for _, val := range []interface{}{name, price, city} { + Printfln("Value: %v", val) + } +} + +func main8() { + name := "Alice" + price := 279 + city := "London" + incrementOrUpper7(&name, &price, &city) + for _, val := range []interface{}{name, price, city} { + Printfln("Value: %v", val) + } +} + +func main9() { + Printfln("\nmain9:") + name := "Alice" + price := 279 + city := "London" + setAll9("New String", &name, &price, &city) + setAll9(10, &name, &price, &city) + for _, val := range []interface{}{name, price, city} { + Printfln("Value: %v", val) + } +} + +func main10() { + Printfln("\nmain10:") + + city := "London" + + citiesSlice := []string{"Paris", "Rome", "London"} + Printfln("Found #1: %v", contains(citiesSlice, city)) + + sliceOfSlices := [][]string{citiesSlice, {"First", "Second", "Third"}} + Printfln("Found #2: %v", contains(sliceOfSlices, citiesSlice)) +} + +func main11() { + Printfln("\nmain11:") + + city := "London" + + citiesSlice := []string{"Paris", "Rome", "London"} + Printfln("Found #1: %v", contains11(citiesSlice, city)) + + sliceOfSlices := [][]string{citiesSlice, {"First", "Second", "Third"}} + Printfln("Found #2: %v", contains11(sliceOfSlices, citiesSlice)) +} + +func main12() { + Printfln("\nmain12:") + name := "Alice" + price := 279 + + newVal, ok := convert12(price, 100.00) + Printfln("Converted %v: %v, %T", ok, newVal, newVal) + newVal, ok = convert12(name, 100.00) + Printfln("Converted %v: %v, %T", ok, newVal, newVal) +} + +func main13() { + Printfln("\nmain13:") + name := "Alice" + price := 279 + + newVal, ok := convert13(price, 100.00) + Printfln("Converted %v: %v, %T", ok, newVal, newVal) + newVal, ok = convert13(name, 100.00) + Printfln("Converted %v: %v, %T", ok, newVal, newVal) + + newVal, ok = convert13(5000, int8(100)) + Printfln("Converted %v: %v, %T", ok, newVal, newVal) + +} + +func main14() { + Printfln("\nmain14:") + name := "Alice" + price := 279 + city := "London" + swap(&name, &city) + + for _, val := range []interface{}{name, price, city} { + Printfln("Value: %v", val) + } + +} diff --git a/27-reflection/reflection/types.go b/27-reflection/reflection/types.go index df933f9..3a988d0 100644 --- a/27-reflection/reflection/types.go +++ b/27-reflection/reflection/types.go @@ -8,3 +8,8 @@ type Product struct { type Customer struct { Name, City string } + +type Payment struct { + Currency string + Amount float64 +}