github.com/tencent/goom@v1.0.1/arg/value.go (about) 1 package arg 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 "strings" 8 "unsafe" 9 10 "github.com/tencent/goom/internal/hack" 11 "github.com/tencent/goom/internal/iface" 12 ) 13 14 // I2V []interface convert to []reflect.Value 将interface元素类型的数组,转换成reflect.Value元素类型的数组 15 func I2V(params []interface{}, types []reflect.Type) []reflect.Value { 16 if len(params) != len(types) { 17 panic(fmt.Sprintf("param lenth mismatch,must: %d, actual: %d", len(types), len(params))) 18 } 19 values := make([]reflect.Value, len(params)) 20 for i, a := range params { 21 values[i] = toValue(a, types[i]) 22 } 23 return values 24 } 25 26 // toValue 将interface参数值转化为reflect.Value值 27 func toValue(r interface{}, out reflect.Type) reflect.Value { 28 v := reflect.ValueOf(r) 29 if r != nil && v.Type() != out && (out.Kind() == reflect.Struct || out.Kind() == reflect.Ptr) { 30 if v.Type().Size() != out.Size() { 31 panic(fmt.Sprintf("type mismatch,must: %s, actual: %v", v.Type(), out)) 32 } 33 // 类型强制转换,适用于结构体 fake 场景 34 v = cast(v, out) 35 } 36 37 if r == nil && (out.Kind() == reflect.Interface || out.Kind() == reflect.Ptr || out.Kind() == reflect.Slice || 38 out.Kind() == reflect.Map || out.Kind() == reflect.Array || out.Kind() == reflect.Chan) { 39 v = reflect.Zero(reflect.SliceOf(out).Elem()) 40 } else if v.Type().Kind() == reflect.Ptr && 41 v.Type() == reflect.TypeOf(&iface.IContext{}) { 42 panic("goom not support Return() API when returns mocked interface type, use Apply() API instead.") 43 } else if r != nil && out.Kind() == reflect.Interface { 44 45 ptr := reflect.New(out) 46 ptr.Elem().Set(v) 47 v = ptr.Elem() 48 } 49 return v 50 } 51 52 // cast 将reflect.Value类型强制转换为执行type类型的reflect.Value 53 func cast(v reflect.Value, typ reflect.Type) reflect.Value { 54 originV := (*hack.Value)(unsafe.Pointer(&v)) 55 newV := reflect.NewAt(typ, originV.Ptr).Elem() 56 newVHack := (*hack.Value)(unsafe.Pointer(&newV)) 57 v = *(*reflect.Value)(unsafe.Pointer(&hack.Value{ 58 Typ: newVHack.Typ, 59 Ptr: originV.Ptr, 60 Flag: originV.Flag, 61 })) 62 63 return v 64 } 65 66 // V2I []reflect.Value convert to []interface 将reflect.Value元素类型的数组,转换成interface元素类型的数组 67 func V2I(params []reflect.Value, types []reflect.Type) []interface{} { 68 values := make([]interface{}, len(params)) 69 for i, a := range params { 70 if (types[i].Kind() == reflect.Interface || types[i].Kind() == reflect.Ptr) && isZero(a) { 71 values[i] = nil 72 } else { 73 values[i] = a.Interface() 74 } 75 } 76 return values 77 } 78 79 // SprintV []reflect.Value print to string 将[]reflect.Value参数列表转换为string用于打印输出 80 func SprintV(params []reflect.Value) string { 81 s := make([]string, 0, len(params)) 82 for _, a := range params { 83 if (a.Kind() == reflect.Interface || a.Kind() == reflect.Ptr) && isZero(a) { 84 s = append(s, "nil") 85 } else { 86 s = append(s, fmt.Sprintf("%v", a.Interface())) 87 } 88 } 89 return strings.Join(s, ",") 90 } 91 92 // ToExpr 将[]interface{}参数转换成[]Expr 93 func ToExpr(params []interface{}, types []reflect.Type) ([]Expr, error) { 94 if len(params) != len(types) { 95 return nil, fmt.Errorf("param lenth mismatch,must: %d, actual: %d", len(types), len(params)) 96 } 97 // TODO results check 98 expressions := make([]Expr, len(params)) 99 for i, a := range params { 100 if expr, ok := a.(Expr); ok { 101 expressions[i] = expr 102 } else { 103 // 默认使用 equals 表达式 104 expressions[i] = Equals(a) 105 } 106 err := expressions[i].Resolve([]reflect.Type{types[i]}) 107 if err != nil { 108 return nil, err 109 } 110 } 111 return expressions, nil 112 } 113 114 // isZero reports whether v is the zero value for its type. 115 // It panics if the argument is invalid. 116 func isZero(v reflect.Value) bool { 117 switch v.Kind() { 118 case reflect.Bool: 119 return !v.Bool() 120 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 121 return v.Int() == 0 122 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 123 return v.Uint() == 0 124 case reflect.Float32, reflect.Float64: 125 return math.Float64bits(v.Float()) == 0 126 case reflect.Complex64, reflect.Complex128: 127 c := v.Complex() 128 return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 129 case reflect.Array: 130 for i := 0; i < v.Len(); i++ { 131 if !isZero(v.Index(i)) { 132 return false 133 } 134 } 135 return true 136 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: 137 return v.IsNil() 138 case reflect.String: 139 return v.Len() == 0 140 case reflect.Struct: 141 for i := 0; i < v.NumField(); i++ { 142 if !isZero(v.Field(i)) { 143 return false 144 } 145 } 146 return true 147 default: 148 return true 149 } 150 }