diff --git a/27-reflection/reflection/functions.go b/27-reflection/reflection/functions.go new file mode 100644 index 0000000..e22bb38 --- /dev/null +++ b/27-reflection/reflection/functions.go @@ -0,0 +1,13 @@ +package main + +func Find(slice []string, vals ...string) (matches bool) { + for _, item := range slice { + for _, val := range vals { + if item == val { + matches = true + return + } + } + } + return +} diff --git a/27-reflection/reflection/interfaces.go b/27-reflection/reflection/interfaces.go new file mode 100644 index 0000000..207f0fe --- /dev/null +++ b/27-reflection/reflection/interfaces.go @@ -0,0 +1,32 @@ +package main + +import "fmt" + +type NamedItem interface { + GetName() string + unexportedMethod() +} + +type CurrencyItem interface { + GetAmount() string + currencyName() string +} + +func (p *Product) GetName() string { + return p.Name +} + +func (p *Product) GetAmount() string { + return fmt.Sprintf("$%.2f", p.Price) +} + +func (p *Product) currencyName() string { + return "USD" +} + +func (p *Product) unexportedMethod() { +} + +func (c *Customer) GetName() string { + return c.Name +} diff --git a/27-reflection/reflection/main.go b/27-reflection/reflection/main.go index 97cd9ee..9726651 100644 --- a/27-reflection/reflection/main.go +++ b/27-reflection/reflection/main.go @@ -25,4 +25,6 @@ func main() { main25() main26() main27() + + main28() } diff --git a/27-reflection/reflection/methods.go b/27-reflection/reflection/methods.go new file mode 100644 index 0000000..d1951d4 --- /dev/null +++ b/27-reflection/reflection/methods.go @@ -0,0 +1,9 @@ +package main + +func (p Purchase) calcTax(taxRate float64) float64 { + return p.Price * taxRate +} + +func (p Purchase) calcTotal() float64 { + return p.Price + p.calcTax(0.20) +} diff --git a/27-reflection/reflection/re3.go b/27-reflection/reflection/re3.go new file mode 100644 index 0000000..723ea45 --- /dev/null +++ b/27-reflection/reflection/re3.go @@ -0,0 +1,77 @@ +package main + +import ( + "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 main28() { + Printfln("\nmain28:") + + inspectFuncType(Find) + + names := []string{"Alice", "Bob", "Charlie"} + invokeFunction(Find, names, "London", "Bob") + + results := mapSlice(names, strings.ToUpper) + Printfln("Results: %v", results) +}