package gocommon import ( "encoding/binary" "encoding/json" "fmt" "io" "math/rand" "path" "reflect" "strconv" "strings" "sync/atomic" "time" "repositories.action2quare.com/ayo/gocommon/flagx" ) var devflag = flagx.Bool("dev", false, "") var sequenceStart = rand.Uint32() func MakeHttpHandlerPattern(n ...string) string { r := "/" + path.Join(n...) if strings.HasSuffix(n[len(n)-1], "/") { return r + "/" } return r } func MakeLocalUniqueId() string { var b [10]byte now := time.Now() binary.BigEndian.PutUint32(b[6:10], uint32(now.Unix())) binary.BigEndian.PutUint32(b[3:7], uint32(now.Nanosecond())) binary.BigEndian.PutUint32(b[0:4], atomic.AddUint32(&sequenceStart, 1)) u := binary.LittleEndian.Uint64(b[2:]) a := strconv.FormatUint(u, 36) return a[1:] } func SerializeInterface(w io.Writer, val interface{}) (err error) { if val == nil { return nil } value := reflect.ValueOf(val) encoder := json.NewEncoder(w) switch value.Kind() { case reflect.String: _, err = w.Write([]byte(value.String())) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: _, err = w.Write([]byte(fmt.Sprintf("%d", value.Int()))) case reflect.Float32, reflect.Float64: _, err = w.Write([]byte(fmt.Sprintf("%f", value.Float()))) case reflect.Bool: if value.Bool() { _, err = w.Write([]byte("true")) } else { _, err = w.Write([]byte("false")) } case reflect.Slice: switch value.Type().Elem().Kind() { case reflect.Uint8: _, err = w.Write(value.Bytes()) default: var conv []interface{} for i := 0; i < value.Len(); i++ { conv = append(conv, value.Index(i).Interface()) } if len(conv) == 0 { _, err = w.Write([]byte("[]")) } else { err = encoder.Encode(conv) } } case reflect.Interface, reflect.Struct, reflect.Map: if value.Kind() == reflect.Struct { err = encoder.Encode(value.Interface()) } else if !value.IsNil() { err = encoder.Encode(value.Interface()) } case reflect.Ptr: if !value.IsNil() { if wro, ok := value.Interface().(io.WriterTo); ok { _, err = wro.WriteTo(w) } else { err = json.NewEncoder(w).Encode(value.Interface()) } } } return } func ShrinkSlice[T any](in []T, compare func(elem T) bool) []T { cursor := 0 for i := 0; i < len(in); i++ { if compare(in[i]) { continue } in[cursor] = in[i] cursor++ } return in[:cursor] } func FindOneInSlice[T any](in []T, compare func(elem *T) bool) (int, *T) { for i, e := range in { if compare(&e) { return i, &e } } return -1, nil }