436 lines
9.4 KiB
Go
436 lines
9.4 KiB
Go
package utils
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"math"
|
||
"net/url"
|
||
"reflect"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"git.rosy.net.cn/baseapi"
|
||
"github.com/fatih/structs"
|
||
)
|
||
|
||
var (
|
||
DefaultTimeValue = Str2Time("1970-01-01 00:00:00")
|
||
ZeroTimeValue = time.Time{}
|
||
)
|
||
|
||
func GetConcretValue(value reflect.Value) reflect.Value {
|
||
for {
|
||
if value.Kind() == reflect.Interface || value.Kind() == reflect.Ptr {
|
||
value = value.Elem()
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
return value
|
||
}
|
||
|
||
func UnmarshalUseNumber(data []byte, result interface{}) error {
|
||
err := TryUnmarshalUseNumber(data, result)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Infof("decode data:%v, error:%v", string(data), err)
|
||
}
|
||
return err
|
||
}
|
||
|
||
func TryUnmarshalUseNumber(data []byte, result interface{}) error {
|
||
d := json.NewDecoder(bytes.NewReader(data))
|
||
d.UseNumber()
|
||
return d.Decode(result)
|
||
}
|
||
|
||
// 这个函数将解析json,返回的map中的字段类型与structObj中的完全一样的
|
||
func Unmarshal2Map(data []byte, structObj interface{}) (resultMap map[string]interface{}, err error) {
|
||
if err = json.Unmarshal(data, structObj); err == nil {
|
||
if err = json.Unmarshal(data, &resultMap); err == nil {
|
||
m := Struct2MapByJson(structObj)
|
||
for k := range resultMap {
|
||
if value, ok := m[k]; ok {
|
||
resultMap[k] = value
|
||
} else {
|
||
delete(resultMap, k)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return resultMap, err
|
||
}
|
||
|
||
func MustMarshal(obj interface{}) []byte {
|
||
byteArr, err := json.Marshal(obj)
|
||
if err != nil {
|
||
panic(fmt.Sprintf("err when Marshal obj:%v with error:%v", obj, err))
|
||
}
|
||
return byteArr
|
||
}
|
||
|
||
func TryInterface2Int64(data interface{}) (num int64, err error) {
|
||
if data == nil {
|
||
return num, errors.New("data is nil")
|
||
}
|
||
if dataNumber, ok := data.(int64); ok {
|
||
return dataNumber, nil
|
||
}
|
||
if dataNumber, ok := data.(int); ok {
|
||
return int64(dataNumber), nil
|
||
}
|
||
dataNumber, ok := data.(json.Number)
|
||
if !ok {
|
||
return 0, fmt.Errorf("data is not json.Number:%v to int64", data)
|
||
}
|
||
retVal, err := dataNumber.Int64()
|
||
if err != nil {
|
||
return num, err
|
||
}
|
||
return retVal, nil
|
||
}
|
||
|
||
func MustInterface2Int64(data interface{}) int64 {
|
||
retVal, err := TryInterface2Int64(data)
|
||
if err != nil {
|
||
panic(err.Error())
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2Int64WithDefault(data interface{}, defValue int64) int64 {
|
||
retVal, err := TryInterface2Int64(data)
|
||
if err != nil {
|
||
return defValue
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2DirectIntWithDefault(data interface{}, defValue int) int {
|
||
if data == nil {
|
||
return defValue
|
||
}
|
||
return data.(int)
|
||
}
|
||
|
||
func TryInterface2Float64(data interface{}) (num float64, err error) {
|
||
if data == nil {
|
||
return num, errors.New("data is nil")
|
||
}
|
||
if dataNumber, ok := data.(float64); ok {
|
||
return dataNumber, nil
|
||
}
|
||
if dataNumber, ok := data.(float32); ok {
|
||
return float64(dataNumber), nil
|
||
}
|
||
dataNumber, ok := data.(json.Number)
|
||
if !ok {
|
||
return num, fmt.Errorf("data is not json.Number:%v", data)
|
||
}
|
||
retVal, err := dataNumber.Float64()
|
||
if err != nil {
|
||
return num, err
|
||
}
|
||
return retVal, nil
|
||
}
|
||
|
||
func MustInterface2Float64(data interface{}) float64 {
|
||
retVal, err := TryInterface2Float64(data)
|
||
if err != nil {
|
||
panic(err.Error())
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2FloatWithDefault(data interface{}, defValue float64) (retVal float64) {
|
||
retVal, err := TryInterface2Float64(data)
|
||
if err != nil {
|
||
return defValue
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2String(data interface{}) string {
|
||
if data == nil {
|
||
return ""
|
||
}
|
||
return data.(string)
|
||
}
|
||
|
||
func Interface2Int64List(data interface{}) []int64 {
|
||
if data == nil {
|
||
return nil
|
||
}
|
||
list := data.([]interface{})
|
||
retVal := make([]int64, len(list))
|
||
for k, v := range list {
|
||
retVal[k] = MustInterface2Int64(v)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2StringList(data interface{}) []string {
|
||
if data == nil {
|
||
return nil
|
||
}
|
||
list := data.([]interface{})
|
||
retVal := make([]string, len(list))
|
||
for k, v := range list {
|
||
retVal[k] = Interface2String(v)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Interface2Slice(value interface{}) (retVal []interface{}) {
|
||
typeInfo := reflect.TypeOf(value)
|
||
if typeInfo.Kind() != reflect.Slice {
|
||
panic("list must be slice type!")
|
||
}
|
||
if value != nil {
|
||
valueInfo := reflect.ValueOf(value)
|
||
retVal = make([]interface{}, valueInfo.Len())
|
||
for i := 0; i < valueInfo.Len(); i++ {
|
||
retVal[i] = valueInfo.Index(i).Interface()
|
||
}
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Slice2MapSlice(data []interface{}) []map[string]interface{} {
|
||
retVal := make([]map[string]interface{}, len(data))
|
||
for k, v := range data {
|
||
retVal[k] = v.(map[string]interface{})
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Slice2int64Slice(data []interface{}) []int64 {
|
||
retVal := make([]int64, len(data))
|
||
for k, v := range data {
|
||
retVal[k] = MustInterface2Int64(v)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Slice2StringSlice(data []interface{}) []string {
|
||
retVal := make([]string, len(data))
|
||
for k, v := range data {
|
||
retVal[k] = Interface2String(v)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
//
|
||
func Bool2String(value bool) string {
|
||
if value {
|
||
return "true"
|
||
}
|
||
return "false"
|
||
}
|
||
|
||
func Bool2Int(value bool) int {
|
||
if value {
|
||
return 1
|
||
}
|
||
return 0
|
||
}
|
||
|
||
func Str2Int64WithDefault(str string, defValue int64) int64 {
|
||
retVal, err := strconv.ParseInt(str, 10, 64)
|
||
if err != nil {
|
||
return defValue
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Str2Int64(str string) int64 {
|
||
retVal, err := strconv.ParseInt(str, 10, 64)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Errorf("error when convert %s to int64", str)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Str2Float64WithDefault(str string, defValue float64) float64 {
|
||
retVal, err := strconv.ParseFloat(str, 64)
|
||
if err != nil {
|
||
retVal = defValue
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Str2Float64(str string) float64 {
|
||
retVal, err := strconv.ParseFloat(str, 64)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Errorf("error when convert %s to float64", str)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Int64ToStr(value int64) string {
|
||
return strconv.FormatInt(value, 10)
|
||
}
|
||
|
||
func Int2Str(value int) string {
|
||
return strconv.Itoa(value)
|
||
}
|
||
|
||
func Float64TwoInt64(data float64) int64 {
|
||
return int64(math.Round(data))
|
||
}
|
||
|
||
// timestamp is in second
|
||
func Timestamp2Str(timestamp int64) string {
|
||
return Time2Str(Timestamp2Time(timestamp))
|
||
}
|
||
|
||
func Timestamp2Time(timestamp int64) time.Time {
|
||
const normalTimestamp = 1533709322
|
||
if timestamp > normalTimestamp*100 { // 传成毫秒了
|
||
baseapi.SugarLogger.Errorf("Timestamp2Time wrong timestamp:%d", timestamp)
|
||
timestamp = timestamp / 1000
|
||
}
|
||
return time.Unix(timestamp, 0)
|
||
}
|
||
|
||
func Time2Str(t time.Time) string {
|
||
return t.Format("2006-01-02 15:04:05")
|
||
}
|
||
|
||
func Time2TimeStr(t time.Time) string {
|
||
return t.Format("15:04:05")
|
||
}
|
||
|
||
func Str2Time(timeStr string) time.Time {
|
||
retVal, err := TryStr2Time(timeStr)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Errorf("time.ParseInLocation failed, timeStr:%v, error:%v", timeStr, err)
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func TryStr2Time(timeStr string) (time.Time, error) {
|
||
timeStr = strings.Replace(timeStr, "T", " ", 1)
|
||
if strings.Index(timeStr, " ") == -1 {
|
||
timeStr += " 00:00:00"
|
||
}
|
||
maxTimeStrLen := len("2018-05-03 09:18:40")
|
||
if len(timeStr) > maxTimeStrLen {
|
||
timeStr = timeStr[:maxTimeStrLen]
|
||
}
|
||
return time.ParseInLocation("2006-1-2 15:4:5", timeStr, time.Local)
|
||
}
|
||
|
||
func Str2TimeWithDefault(timeStr string, defValue time.Time) time.Time {
|
||
retVal, err := TryStr2Time(timeStr)
|
||
if err != nil {
|
||
return defValue
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func IsTimeZero(timeValue time.Time) bool {
|
||
return timeValue == DefaultTimeValue || timeValue == ZeroTimeValue
|
||
}
|
||
|
||
func HTTPBody2Values(data []byte, needDecode bool) (url.Values, error) {
|
||
bodyStr := string(data)
|
||
if needDecode {
|
||
bodyStr1, err := url.QueryUnescape(bodyStr)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Errorf("QueryUnescape error:%v, bodyStr:%v", err, bodyStr)
|
||
return nil, err
|
||
}
|
||
bodyStr = bodyStr1
|
||
}
|
||
result, err := url.ParseQuery(bodyStr)
|
||
if err != nil {
|
||
baseapi.SugarLogger.Errorf("ParseQuery error:%v, bodyStr:%v", err, bodyStr)
|
||
return nil, err
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func Params2Map(key1, value1 interface{}, kv ...interface{}) (retVal map[string]interface{}) {
|
||
retVal = make(map[string]interface{})
|
||
retVal[key1.(string)] = value1
|
||
|
||
key := ""
|
||
for index, v := range kv {
|
||
if index%2 == 0 {
|
||
key = v.(string)
|
||
} else {
|
||
retVal[key] = v
|
||
}
|
||
}
|
||
|
||
return retVal
|
||
}
|
||
|
||
func URLValues2Map(values url.Values) (retVal map[string]interface{}) {
|
||
retVal = make(map[string]interface{})
|
||
for k := range values {
|
||
retVal[k], _ = url.QueryUnescape(values.Get(k))
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Map2URLValues(mapData map[string]interface{}) (retVal url.Values) {
|
||
retVal = make(url.Values)
|
||
for k, v := range mapData {
|
||
retVal.Set(k, fmt.Sprint(v))
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func MapKV2List(mapData map[string]interface{}) []map[string]interface{} {
|
||
retVal := make([]map[string]interface{}, len(mapData))
|
||
index := 0
|
||
for _, v := range mapData {
|
||
retVal[index] = v.(map[string]interface{})
|
||
index++
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Format4Output(obj interface{}, isSingleLine bool) (retVal string) {
|
||
retVal, ok := obj.(string)
|
||
if !ok {
|
||
var (
|
||
result []byte
|
||
err error
|
||
)
|
||
if isSingleLine {
|
||
if result, err = json.Marshal(obj); err == nil {
|
||
retVal = string(result)
|
||
}
|
||
} else {
|
||
if result, err = json.MarshalIndent(obj, "", "\t"); err == nil {
|
||
retVal = string(result)
|
||
}
|
||
}
|
||
if err != nil {
|
||
baseapi.SugarLogger.Infof("Format4Output Marshal:%v failed with error:%v", obj, err)
|
||
retVal = fmt.Sprintf("%v", obj)
|
||
}
|
||
}
|
||
return retVal
|
||
}
|
||
|
||
func Map2KeySlice(flagMap map[string]int) (keyList []string) {
|
||
for k, v := range flagMap {
|
||
if v != 0 {
|
||
keyList = append(keyList, k)
|
||
}
|
||
}
|
||
return keyList
|
||
}
|
||
|
||
func Struct2MapByJson(obj interface{}) (mapData map[string]interface{}) {
|
||
structsObj := structs.New(obj)
|
||
structsObj.TagName = "json"
|
||
return structsObj.Map()
|
||
}
|