github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/convert.go (about) 1 package f 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "reflect" 8 "strconv" 9 "unsafe" 10 ) 11 12 // String converts byte slice to a string without memory allocation. 13 // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ 14 func String(b []byte) string { 15 return *(*string)(unsafe.Pointer(&b)) 16 } 17 18 // ToString convert number to string. 19 func ToString(val interface{}) (str string) { 20 switch tVal := val.(type) { 21 case int: 22 str = strconv.FormatInt(int64(tVal), 10) 23 case int8: 24 str = strconv.FormatInt(int64(tVal), 10) 25 case int16: 26 str = strconv.FormatInt(int64(tVal), 10) 27 case int32: 28 str = strconv.FormatInt(int64(tVal), 10) 29 case int64: 30 str = strconv.FormatInt(tVal, 10) 31 case uint: 32 str = strconv.FormatUint(uint64(tVal), 10) 33 case uint8: 34 str = strconv.FormatUint(uint64(tVal), 10) 35 case uint16: 36 str = strconv.FormatUint(uint64(tVal), 10) 37 case uint32: 38 str = strconv.FormatUint(uint64(tVal), 10) 39 case uint64: 40 str = strconv.FormatUint(tVal, 10) 41 case float32, float64: 42 str = fmt.Sprintf("%g", tVal) 43 case string: 44 str = tVal 45 case []byte: 46 str = String(tVal) 47 case nil: 48 str = "" 49 default: 50 if t, ok := tVal.(fmt.Stringer); ok { 51 str = t.String() 52 } else if t, ok := tVal.(io.Reader); ok { 53 buf := new(bytes.Buffer) 54 if n, _ := buf.ReadFrom(t); n > 0 { 55 return buf.String() 56 } 57 } else { 58 str = fmt.Sprintf("%v", tVal) 59 } 60 } 61 return 62 } 63 64 // ToJSON convert the input to a valid JSON string. 65 func ToJSON(obj interface{}) (string, error) { 66 res, err := EncodeJson(obj) 67 if err != nil { 68 res = []byte("") 69 } 70 return string(res), err 71 } 72 73 // Map check and convert the Map or Ptr to a map[string]interface{}. 74 func Map(obj interface{}) (map[string]interface{}, bool) { 75 if obj == nil { 76 return nil, false 77 } 78 79 var ( 80 rv reflect.Value 81 ok bool 82 ) 83 84 if rv, ok = obj.(reflect.Value); !ok { 85 rv = reflect.ValueOf(obj) 86 } 87 88 if rv.Kind() == reflect.Ptr { 89 rv = rv.Elem() 90 } 91 92 if rv.Kind() == reflect.Map { 93 m := map[string]interface{}{} 94 for _, k := range rv.MapKeys() { 95 m[k.String()] = rv.MapIndex(k).Interface() 96 } 97 return m, true 98 } 99 return nil, false 100 } 101 102 // MapMerge recursively merges the src and dst maps. Key conflicts are resolved by 103 // preferring src, or recursively descending, if both src and dst are maps. 104 func MapMerge(dst, src map[string]interface{}) map[string]interface{} { 105 for key, srcVal := range src { 106 if dstVal, ok := dst[key]; ok { 107 srcMap, srcMapOk := Map(srcVal) 108 dstMap, dstMapOk := Map(dstVal) 109 if srcMapOk && dstMapOk { 110 srcVal = MapMerge(dstMap, srcMap) 111 } 112 } 113 dst[key] = srcVal 114 } 115 return dst 116 } 117 118 // ToMap convert the struct to a map[string]interface{}. 119 func ToMap(obj interface{}) (map[string]interface{}, error) { 120 out := map[string]interface{}{} 121 v := reflect.ValueOf(obj) 122 if v.Kind() == reflect.Ptr { 123 v = v.Elem() 124 } 125 if v.Kind() != reflect.Struct { 126 return nil, fmt.Errorf("f.ToMap(obj) accepts only structs; got %T", v) 127 } 128 t := v.Type() 129 for i := 0; i < v.NumField(); i++ { 130 f := t.Field(i) 131 if v.Field(i).Kind() == reflect.Struct { 132 innerOut, err := ToMap(v.Field(i).Interface()) 133 if err != nil { 134 return nil, err 135 } 136 out[f.Name] = innerOut 137 } else { 138 out[f.Name] = v.Field(i).Interface() 139 } 140 } 141 return out, nil 142 } 143 144 // ToMapOfTag convert the struct to a map[string]interface{} and a map with the tag's value. 145 func ToMapOfTag(obj interface{}, tag string) (map[string]interface{}, map[string]interface{}, error) { 146 out := map[string]interface{}{} 147 tags := map[string]interface{}{} 148 149 v := reflect.ValueOf(obj) 150 if v.Kind() == reflect.Ptr { 151 v = v.Elem() 152 } 153 if v.Kind() != reflect.Struct { 154 return nil, nil, fmt.Errorf("f.ToMapOfTag(obj,tag) accepts only structs; got %T", v) 155 } 156 t := v.Type() 157 for i := 0; i < v.NumField(); i++ { 158 f := t.Field(i) 159 if v.Field(i).Kind() == reflect.Struct { 160 innerOut, innerTags, err := ToMapOfTag(v.Field(i).Interface(), tag) 161 if err != nil { 162 return nil, nil, err 163 } 164 out[f.Name] = innerOut 165 tags[f.Name] = innerTags 166 } else { 167 out[f.Name] = v.Field(i).Interface() 168 tags[f.Name] = f.Tag.Get(tag) 169 } 170 } 171 return out, tags, nil 172 } 173 174 // ToFloat convert the input string to a float, or 0.0 if the input is not a float. 175 func ToFloat(str string) (float64, error) { 176 res, err := strconv.ParseFloat(str, 64) 177 if err != nil { 178 res = 0.0 179 } 180 return res, err 181 } 182 183 // Bytes converts string to a byte slice without memory allocation. 184 // NOTE: panic if modify the member value of the []byte. 185 func Bytes(s string) []byte { 186 //return *(*[]byte)(unsafe.Pointer(&s)) 187 return *(*[]byte)(unsafe.Pointer( 188 &struct { 189 string 190 Cap int 191 }{s, len(s)}, 192 )) 193 } 194 195 // ToBytes converts string to a byte slice without memory allocation. 196 // NOTE: panic if modify the member value of the []byte. 197 func ToBytes(s string) []byte { 198 sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) 199 bh := reflect.SliceHeader{Data: sh.Data, Len: sh.Len, Cap: sh.Len} 200 return *(*[]byte)(unsafe.Pointer(&bh)) 201 } 202 203 // BytesRepeat returns a new byte slice consisting of count copies of b. 204 func BytesRepeat(b byte, count int) []byte { 205 nb := make([]byte, count) 206 for i := 0; i < count; i++ { 207 nb[i] = b 208 } 209 return nb 210 } 211 212 // BytesFromPtr converts a pointer to a byte slice without memory allocation. 213 func BytesFromPtr(p uintptr, b []byte, off int64, size int32) int { 214 bh := reflect.SliceHeader{Data: p, Len: int(size), Cap: int(size)} 215 bb := *(*[]byte)(unsafe.Pointer(&bh)) 216 return copy(b, bb[off:size]) 217 } 218 219 // BytesToPtr converts a byte slice to a pointer without memory allocation. 220 func BytesToPtr(b []byte, p uintptr, off int64, size int32) int { 221 bh := reflect.SliceHeader{Data: p, Len: int(size), Cap: int(size)} 222 bb := *(*[]byte)(unsafe.Pointer(&bh)) 223 return copy(bb[off:], b) 224 } 225 226 // StringsConvert converts the string slice to a new slice using fn. 227 // If fn returns error, exit the conversion and return the error. 228 func StringsConvert(a []string, fn func(string) (string, error)) ([]string, error) { 229 ret := make([]string, len(a)) 230 for i, s := range a { 231 r, err := fn(s) 232 if err != nil { 233 return nil, err 234 } 235 ret[i] = r 236 } 237 return ret, nil 238 } 239 240 // StringsConvertMap converts the string slice to a new map using fn. 241 // If fn returns error, exit the conversion and return the error. 242 func StringsConvertMap(a []string, fn func(string) (string, error)) (map[string]string, error) { 243 ret := make(map[string]string, len(a)) 244 for _, s := range a { 245 r, err := fn(s) 246 if err != nil { 247 return nil, err 248 } 249 ret[s] = r 250 } 251 return ret, nil 252 } 253 254 // StringInSlice finds needle in a slice of strings. 255 func StringInSlice(sliceString []string, needle string) bool { 256 for _, b := range sliceString { 257 if b == needle { 258 return true 259 } 260 } 261 return false 262 }