Files
gocommon/misc.go

102 lines
2.1 KiB
Go

package gocommon
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"math/rand"
"path"
"reflect"
"strconv"
"strings"
"sync/atomic"
"time"
)
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
}