refactor: 后端包结构重构、去除无用的文件

This commit is contained in:
meilin.huang
2022-06-02 17:41:11 +08:00
parent 51d06ab206
commit b2dc9dff0b
234 changed files with 749 additions and 816 deletions

View File

@@ -0,0 +1,33 @@
package utils
// 数组比较
// 依次返回,新增值,删除值,以及不变值
func ArrayCompare(newArr []interface{}, oldArr []interface{}, compareFun func(interface{}, interface{}) bool) ([]interface{}, []interface{}, []interface{}) {
var unmodifierValue []interface{}
ni, oi := 0, 0
for {
if ni >= len(newArr) {
break
}
nv := newArr[ni]
for {
if oi >= len(oldArr) {
oi = 0
break
}
ov := oldArr[oi]
if compareFun(nv, ov) {
unmodifierValue = append(unmodifierValue, nv)
// 新数组移除该位置值
newArr = append(newArr[:ni], newArr[ni+1:]...)
oldArr = append(oldArr[:oi], oldArr[oi+1:]...)
ni = ni - 1
oi = oi - 1
}
oi = oi + 1
}
ni = ni + 1
}
return newArr, oldArr, unmodifierValue
}

View File

@@ -0,0 +1,17 @@
package utils
import (
"fmt"
"testing"
)
func TestArrayCompare(t *testing.T) {
newArr := []interface{}{1, 2, 3, 5}
oldArr := []interface{}{3, 6}
add, del, unmodifier := ArrayCompare(newArr, oldArr, func(i1, i2 interface{}) bool {
return i1.(int) == i2.(int)
})
fmt.Println(add...)
fmt.Println(del...)
fmt.Println(unmodifier...)
}

View File

@@ -0,0 +1,21 @@
package assert
import "fmt"
// 断言条件为真不满足的panic
func IsTrue(condition bool, panicMsg string, params ...interface{}) {
if !condition {
if len(params) != 0 {
panic(fmt.Sprintf(panicMsg, params...))
}
panic(panicMsg)
}
}
func State(condition bool, panicMsg string, params ...interface{}) {
IsTrue(condition, panicMsg, params...)
}
func NotEmpty(str string, panicMsg string, params ...interface{}) {
IsTrue(str != "", panicMsg, params...)
}

View File

@@ -0,0 +1,13 @@
package utils
import (
"crypto/md5"
"encoding/hex"
)
// md5
func Md5(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}

View File

@@ -0,0 +1,14 @@
package utils
import (
"encoding/json"
)
func Json2Map(jsonStr string) map[string]interface{} {
var res map[string]interface{}
if jsonStr == "" {
return res
}
_ = json.Unmarshal([]byte(jsonStr), &res)
return res
}

View File

@@ -0,0 +1,44 @@
package utils
import (
"reflect"
"strconv"
)
func GetString4Map(m map[string]interface{}, key string) string {
return m[key].(string)
}
func GetInt4Map(m map[string]interface{}, key string) int {
i := m[key]
iKind := reflect.TypeOf(i).Kind()
if iKind == reflect.Int {
return i.(int)
}
if iKind == reflect.String {
i, _ := strconv.Atoi(i.(string))
return i
}
return 0
}
// map构造器
type mapBuilder struct {
m map[string]interface{}
}
func MapBuilder(key string, value interface{}) *mapBuilder {
mb := new(mapBuilder)
mb.m = make(map[string]interface{}, 4)
mb.m[key] = value
return mb
}
func (mb *mapBuilder) Put(key string, value interface{}) *mapBuilder {
mb.m[key] = value
return mb
}
func (mb *mapBuilder) ToMap() map[string]interface{} {
return mb.m
}

View File

@@ -0,0 +1,9 @@
package utils
import "runtime"
// 获取调用堆栈信息
func GetStackTrace() string {
var buf [2 << 10]byte
return string(buf[:runtime.Stack(buf[:], false)])
}

View File

@@ -0,0 +1,109 @@
package utils
import (
"bytes"
"strings"
"text/template"
)
// 可判断中文
func StrLen(str string) int {
return len([]rune(str))
}
// 去除字符串左右空字符
func StrTrim(str string) string {
return strings.Trim(str, " ")
}
func SubString(str string, begin, end int) (substr string) {
// 将字符串的转换成[]rune
rs := []rune(str)
lth := len(rs)
// 简单的越界判断
if begin < 0 {
begin = 0
}
if begin >= lth {
begin = lth
}
if end > lth {
end = lth
}
// 返回子串
return string(rs[begin:end])
}
func Camel2Underline(name string) string {
if name == "" {
return ""
}
temp := strings.Split(name, "_")
var s string
for _, v := range temp {
vv := []rune(v)
if len(vv) > 0 {
if bool(vv[0] >= 'a' && vv[0] <= 'z') { //首字母大写
vv[0] -= 32
}
s += string(vv)
}
}
return s
}
func UnicodeIndex(str, substr string) int {
// 子串在字符串的字节位置
result := strings.Index(str, substr)
if result >= 0 {
// 获得子串之前的字符串并转换成[]byte
prefix := []byte(str)[0:result]
// 将子串之前的字符串转换成[]rune
rs := []rune(string(prefix))
// 获得子串之前的字符串的长度,便是子串在字符串的字符位置
result = len(rs)
}
return result
}
// 字符串模板解析
func TemplateResolve(temp string, data interface{}) string {
t, _ := template.New("string-temp").Parse(temp)
var tmplBytes bytes.Buffer
err := t.Execute(&tmplBytes, data)
if err != nil {
panic(err)
}
return tmplBytes.String()
}
func ReverStrTemplate(temp, str string, res map[string]interface{}) {
index := UnicodeIndex(temp, "{")
ei := UnicodeIndex(temp, "}") + 1
next := StrTrim(temp[ei:])
nextContain := UnicodeIndex(next, "{")
nextIndexValue := next
if nextContain != -1 {
nextIndexValue = SubString(next, 0, nextContain)
}
key := temp[index+1 : ei-1]
// 如果后面没有内容了,则取字符串的长度即可
var valueLastIndex int
if nextIndexValue == "" {
valueLastIndex = StrLen(str)
} else {
valueLastIndex = UnicodeIndex(str, nextIndexValue)
}
value := StrTrim(SubString(str, index, valueLastIndex))
res[key] = value
// 如果后面的还有需要解析的,则递归调用解析
if nextContain != -1 {
ReverStrTemplate(next, StrTrim(SubString(str, UnicodeIndex(str, value)+StrLen(value), StrLen(str))), res)
}
}

View File

@@ -0,0 +1,654 @@
package utils
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)
// Copy copy things引用至copier
func Copy(toValue interface{}, fromValue interface{}) (err error) {
var (
isSlice bool
amount = 1
from = Indirect(reflect.ValueOf(fromValue))
to = Indirect(reflect.ValueOf(toValue))
)
if !to.CanAddr() {
return errors.New("copy to value is unaddressable")
}
// Return is from value is invalid
if !from.IsValid() {
return
}
fromType := IndirectType(from.Type())
toType := IndirectType(to.Type())
// Just set it if possible to assign
// And need to do copy anyway if the type is struct
if fromType.Kind() != reflect.Struct && from.Type().AssignableTo(to.Type()) {
to.Set(from)
return
}
if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
return
}
if to.Kind() == reflect.Slice {
isSlice = true
if from.Kind() == reflect.Slice {
amount = from.Len()
}
}
for i := 0; i < amount; i++ {
var dest, source reflect.Value
if isSlice {
// source
if from.Kind() == reflect.Slice {
source = Indirect(from.Index(i))
} else {
source = Indirect(from)
}
// dest
dest = Indirect(reflect.New(toType).Elem())
} else {
source = Indirect(from)
dest = Indirect(to)
}
// check source
if source.IsValid() {
fromTypeFields := deepFields(fromType)
//fmt.Printf("%#v", fromTypeFields)
// Copy from field to field or method
for _, field := range fromTypeFields {
name := field.Name
if fromField := source.FieldByName(name); fromField.IsValid() {
// has field
if toField := dest.FieldByName(name); toField.IsValid() {
if toField.CanSet() {
if !set(toField, fromField) {
if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {
return err
}
}
}
} else {
// try to set to method
var toMethod reflect.Value
if dest.CanAddr() {
toMethod = dest.Addr().MethodByName(name)
} else {
toMethod = dest.MethodByName(name)
}
if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
toMethod.Call([]reflect.Value{fromField})
}
}
}
}
// Copy from method to field
for _, field := range deepFields(toType) {
name := field.Name
var fromMethod reflect.Value
if source.CanAddr() {
fromMethod = source.Addr().MethodByName(name)
} else {
fromMethod = source.MethodByName(name)
}
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {
if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
values := fromMethod.Call([]reflect.Value{})
if len(values) >= 1 {
set(toField, values[0])
}
}
}
}
}
if isSlice {
if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
to.Set(reflect.Append(to, dest.Addr()))
} else if dest.Type().AssignableTo(to.Type().Elem()) {
to.Set(reflect.Append(to, dest))
}
}
}
return
}
// 对结构体的每个字段以及字段值执行doWith回调函数, 包括匿名属性的字段
func DoWithFields(str interface{}, doWith func(fType reflect.StructField, fValue reflect.Value) error) error {
t := IndirectType(reflect.TypeOf(str))
if t.Kind() != reflect.Struct {
return errors.New("非结构体")
}
fieldNum := t.NumField()
v := Indirect(reflect.ValueOf(str))
for i := 0; i < fieldNum; i++ {
ft := t.Field(i)
fv := v.Field(i)
// 如果是匿名属性,则递归调用该方法
if ft.Anonymous {
DoWithFields(fv.Interface(), doWith)
continue
}
err := doWith(ft, fv)
if err != nil {
return err
}
}
return nil
}
func deepFields(reflectType reflect.Type) []reflect.StructField {
var fields []reflect.StructField
if reflectType = IndirectType(reflectType); reflectType.Kind() == reflect.Struct {
for i := 0; i < reflectType.NumField(); i++ {
v := reflectType.Field(i)
if v.Anonymous {
fields = append(fields, deepFields(v.Type)...)
} else {
fields = append(fields, v)
}
}
}
return fields
}
func Indirect(reflectValue reflect.Value) reflect.Value {
for reflectValue.Kind() == reflect.Ptr {
reflectValue = reflectValue.Elem()
}
return reflectValue
}
func IndirectType(reflectType reflect.Type) reflect.Type {
for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
reflectType = reflectType.Elem()
}
return reflectType
}
func set(to, from reflect.Value) bool {
if from.IsValid() {
if to.Kind() == reflect.Ptr {
//set `to` to nil if from is nil
if from.Kind() == reflect.Ptr && from.IsNil() {
to.Set(reflect.Zero(to.Type()))
return true
} else if to.IsNil() {
to.Set(reflect.New(to.Type().Elem()))
}
to = to.Elem()
}
if from.Type().ConvertibleTo(to.Type()) {
to.Set(from.Convert(to.Type()))
} else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {
err := scanner.Scan(from.Interface())
if err != nil {
return false
}
} else if from.Kind() == reflect.Ptr {
return set(to, from.Elem())
} else {
return false
}
}
return true
}
func Map2Struct(m map[string]interface{}, s interface{}) error {
toValue := Indirect(reflect.ValueOf(s))
if !toValue.CanAddr() {
return errors.New("to value is unaddressable")
}
innerStructMaps := getInnerStructMaps(m)
if len(innerStructMaps) != 0 {
for k, v := range innerStructMaps {
var fieldV reflect.Value
if strings.Contains(k, ".") {
fieldV = getFiledValueByPath(k, toValue)
} else {
fieldV = toValue.FieldByName(k)
}
if !fieldV.CanSet() || !fieldV.CanAddr() {
continue
}
fieldT := fieldV.Type().Elem()
if fieldT.Kind() != reflect.Struct {
return errors.New(k + "不是结构体")
}
// 如果值为nil则默认创建一个并赋值
if fieldV.IsNil() {
fieldV.Set(reflect.New(fieldT))
}
err := Map2Struct(v, fieldV.Addr().Interface())
if err != nil {
return err
}
}
}
var err error
for k, v := range m {
if v == nil {
continue
}
k = strings.Title(k)
// 如果key含有下划线则将其转为驼峰
if strings.Contains(k, "_") {
k = Case2Camel(k)
}
fieldV := toValue.FieldByName(k)
if !fieldV.CanSet() {
continue
}
err = decode(k, v, fieldV)
if err != nil {
return err
}
}
return nil
}
func Maps2Structs(maps []map[string]interface{}, structs interface{}) error {
structsV := reflect.Indirect(reflect.ValueOf(structs))
valType := structsV.Type()
valElemType := valType.Elem()
sliceType := reflect.SliceOf(valElemType)
length := len(maps)
valSlice := structsV
if valSlice.IsNil() {
// Make a new slice to hold our result, same size as the original data.
valSlice = reflect.MakeSlice(sliceType, length, length)
}
for i := 0; i < length; i++ {
err := Map2Struct(maps[i], valSlice.Index(i).Addr().Interface())
if err != nil {
return err
}
}
structsV.Set(valSlice)
return nil
}
func getFiledValueByPath(path string, value reflect.Value) reflect.Value {
split := strings.Split(path, ".")
for _, v := range split {
if value.Type().Kind() == reflect.Ptr {
// 如果值为nil则创建并赋值
if value.IsNil() {
value.Set(reflect.New(IndirectType(value.Type())))
}
value = value.Elem()
}
value = value.FieldByName(v)
}
return value
}
func getInnerStructMaps(m map[string]interface{}) map[string]map[string]interface{} {
key2map := make(map[string]map[string]interface{})
for k, v := range m {
if !strings.Contains(k, ".") {
continue
}
lastIndex := strings.LastIndex(k, ".")
prefix := k[0:lastIndex]
m2 := key2map[prefix]
if m2 == nil {
key2map[prefix] = map[string]interface{}{k[lastIndex+1:]: v}
} else {
m2[k[lastIndex+1:]] = v
}
delete(m, k)
}
return key2map
}
// decode等方法摘抄自mapstructure库
func decode(name string, input interface{}, outVal reflect.Value) error {
var inputVal reflect.Value
if input != nil {
inputVal = reflect.ValueOf(input)
// We need to check here if input is a typed nil. Typed nils won't
// match the "input == nil" below so we check that here.
if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() {
input = nil
}
}
if !inputVal.IsValid() {
// If the input value is invalid, then we just set the value
// to be the zero value.
outVal.Set(reflect.Zero(outVal.Type()))
return nil
}
var err error
outputKind := getKind(outVal)
switch outputKind {
case reflect.Int:
err = decodeInt(name, input, outVal)
case reflect.Uint:
err = decodeUint(name, input, outVal)
case reflect.Float32:
err = decodeFloat(name, input, outVal)
case reflect.String:
err = decodeString(name, input, outVal)
case reflect.Ptr:
_, err = decodePtr(name, input, outVal)
default:
// If we reached this point then we weren't able to decode it
return fmt.Errorf("%s: unsupported type: %s", name, outputKind)
}
return err
}
func decodeInt(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
switch {
case dataKind == reflect.Int:
val.SetInt(dataVal.Int())
case dataKind == reflect.Uint:
val.SetInt(int64(dataVal.Uint()))
case dataKind == reflect.Float32:
val.SetInt(int64(dataVal.Float()))
case dataKind == reflect.Bool:
if dataVal.Bool() {
val.SetInt(1)
} else {
val.SetInt(0)
}
case dataKind == reflect.String:
i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits())
if err == nil {
val.SetInt(i)
} else {
return fmt.Errorf("cannot parse '%s' as int: %s", name, err)
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
i, err := jn.Int64()
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
val.SetInt(i)
default:
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'",
name, val.Type(), dataVal.Type())
}
return nil
}
func decodeUint(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
switch {
case dataKind == reflect.Int:
i := dataVal.Int()
if i < 0 {
return fmt.Errorf("cannot parse '%s', %d overflows uint",
name, i)
}
val.SetUint(uint64(i))
case dataKind == reflect.Uint:
val.SetUint(dataVal.Uint())
case dataKind == reflect.Float32:
f := dataVal.Float()
if f < 0 {
return fmt.Errorf("cannot parse '%s', %f overflows uint",
name, f)
}
val.SetUint(uint64(f))
case dataKind == reflect.Bool:
if dataVal.Bool() {
val.SetUint(1)
} else {
val.SetUint(0)
}
case dataKind == reflect.String:
i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits())
if err == nil {
val.SetUint(i)
} else {
return fmt.Errorf("cannot parse '%s' as uint: %s", name, err)
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
i, err := jn.Int64()
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
if i < 0 {
return fmt.Errorf("cannot parse '%s', %d overflows uint",
name, i)
}
val.SetUint(uint64(i))
default:
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'",
name, val.Type(), dataVal.Type())
}
return nil
}
func decodeFloat(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
dataType := dataVal.Type()
switch {
case dataKind == reflect.Int:
val.SetFloat(float64(dataVal.Int()))
case dataKind == reflect.Uint:
val.SetFloat(float64(dataVal.Uint()))
case dataKind == reflect.Float32:
val.SetFloat(dataVal.Float())
case dataKind == reflect.Bool:
if dataVal.Bool() {
val.SetFloat(1)
} else {
val.SetFloat(0)
}
case dataKind == reflect.String:
f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits())
if err == nil {
val.SetFloat(f)
} else {
return fmt.Errorf("cannot parse '%s' as float: %s", name, err)
}
case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number":
jn := data.(json.Number)
i, err := jn.Float64()
if err != nil {
return fmt.Errorf(
"error decoding json.Number into %s: %s", name, err)
}
val.SetFloat(i)
default:
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'",
name, val.Type(), dataVal.Type())
}
return nil
}
func decodeString(name string, data interface{}, val reflect.Value) error {
dataVal := reflect.Indirect(reflect.ValueOf(data))
dataKind := getKind(dataVal)
converted := true
switch {
case dataKind == reflect.String:
val.SetString(dataVal.String())
case dataKind == reflect.Bool:
if dataVal.Bool() {
val.SetString("1")
} else {
val.SetString("0")
}
case dataKind == reflect.Int:
val.SetString(strconv.FormatInt(dataVal.Int(), 10))
case dataKind == reflect.Uint:
val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
case dataKind == reflect.Float32:
val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64))
case dataKind == reflect.Slice,
dataKind == reflect.Array:
dataType := dataVal.Type()
elemKind := dataType.Elem().Kind()
switch elemKind {
case reflect.Uint8:
var uints []uint8
if dataKind == reflect.Array {
uints = make([]uint8, dataVal.Len(), dataVal.Len())
for i := range uints {
uints[i] = dataVal.Index(i).Interface().(uint8)
}
} else {
uints = dataVal.Interface().([]uint8)
}
val.SetString(string(uints))
default:
converted = false
}
default:
converted = false
}
if !converted {
return fmt.Errorf(
"'%s' expected type '%s', got unconvertible type '%s'",
name, val.Type(), dataVal.Type())
}
return nil
}
func decodePtr(name string, data interface{}, val reflect.Value) (bool, error) {
// If the input data is nil, then we want to just set the output
// pointer to be nil as well.
isNil := data == nil
if !isNil {
switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() {
case reflect.Chan,
reflect.Func,
reflect.Interface,
reflect.Map,
reflect.Ptr,
reflect.Slice:
isNil = v.IsNil()
}
}
if isNil {
if !val.IsNil() && val.CanSet() {
nilValue := reflect.New(val.Type()).Elem()
val.Set(nilValue)
}
return true, nil
}
// Create an element of the concrete (non pointer) type and decode
// into that. Then set the value of the pointer to this type.
valType := val.Type()
valElemType := valType.Elem()
if val.CanSet() {
realVal := val
if realVal.IsNil() {
realVal = reflect.New(valElemType)
}
if err := decode(name, data, reflect.Indirect(realVal)); err != nil {
return false, err
}
val.Set(realVal)
} else {
if err := decode(name, data, reflect.Indirect(val)); err != nil {
return false, err
}
}
return false, nil
}
func getKind(val reflect.Value) reflect.Kind {
kind := val.Kind()
switch {
case kind >= reflect.Int && kind <= reflect.Int64:
return reflect.Int
case kind >= reflect.Uint && kind <= reflect.Uint64:
return reflect.Uint
case kind >= reflect.Float32 && kind <= reflect.Float64:
return reflect.Float32
default:
return kind
}
}
// 下划线写法转为驼峰写法
func Case2Camel(name string) string {
name = strings.Replace(name, "_", " ", -1)
name = strings.Title(name)
return strings.Replace(name, " ", "", -1)
}
func IsBlank(value reflect.Value) bool {
switch value.Kind() {
case reflect.String:
return value.Len() == 0
case reflect.Bool:
return !value.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return value.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return value.Uint() == 0
case reflect.Float32, reflect.Float64:
return value.Float() == 0
case reflect.Interface, reflect.Ptr:
return value.IsNil()
}
return reflect.DeepEqual(value.Interface(), reflect.Zero(value.Type()).Interface())
}

View File

@@ -0,0 +1,194 @@
package utils
import (
"fmt"
"reflect"
"strings"
"testing"
"time"
)
type Src struct {
Id *int64 `json:"id"`
Username string `json:"username"`
CreateTime time.Time `json:"time"`
UpdateTime time.Time
Inner *SrcInner
}
type SrcInner struct {
Name string
Desc string
Id int64
Dest *Dest
}
type Dest struct {
Username string
Id int64
CreateTime time.Time
Inner *DestInner
}
type DestInner struct {
Desc string
}
func TestDeepFields(t *testing.T) {
////src := Src{Username: "test", Id: 1000, CreateTime: time.Now()}
//si := SrcInner{Desc: "desc"}
//src.Inner = &si
////src.Id = 1222
//dest := new(Dest)
//err := structutils.Copy(dest, src)
//if err != nil {
// fmt.Println(err.Error())
//} else {
// fmt.Println(dest)
//}
}
func TestGetFieldNames(t *testing.T) {
//names := structutils.GetFieldNames(new(Src))
//fmt.Println(names)
}
func TestMaps2Structs(t *testing.T) {
mapInstance := make(map[string]interface{})
mapInstance["Username"] = "liang637210"
mapInstance["Id"] = 28
mapInstance["CreateTime"] = time.Now()
mapInstance["Creator"] = "createor"
mapInstance["Inner.Id"] = 10
mapInstance["Inner.Name"] = "hahah"
mapInstance["Inner.Desc"] = "inner desc"
mapInstance["Inner.Dest.Username"] = "inner dest uername"
mapInstance["Inner.Dest.Inner.Desc"] = "inner dest inner desc"
mapInstance2 := make(map[string]interface{})
mapInstance2["Username"] = "liang6372102"
mapInstance2["Id"] = 282
mapInstance2["CreateTime"] = time.Now()
mapInstance2["Creator"] = "createor2"
mapInstance2["Inner.Id"] = 102
mapInstance2["Inner.Name"] = "hahah2"
mapInstance2["Inner.Desc"] = "inner desc2"
mapInstance2["Inner.Dest.Username"] = "inner dest uername2"
mapInstance2["Inner.Dest.Inner.Desc"] = "inner dest inner desc2"
maps := make([]map[string]interface{}, 2)
maps[0] = mapInstance
maps[1] = mapInstance2
res := new([]Src)
err := Maps2Structs(maps, res)
if err != nil {
fmt.Println(err)
}
}
func TestMap2Struct(t *testing.T) {
mapInstance := make(map[string]interface{})
mapInstance["Username"] = "liang637210"
mapInstance["Id"] = 12
mapInstance["CreateTime"] = time.Now()
mapInstance["Creator"] = "createor"
mapInstance["Inner.Id"] = nil
mapInstance["Inner.Name"] = "hahah"
mapInstance["Inner.Desc"] = "inner desc"
mapInstance["Inner.Dest.Username"] = "inner dest uername"
mapInstance["Inner.Dest.Inner.Desc"] = "inner dest inner desc"
//innerMap := make(map[string]interface{})
//innerMap["Name"] = "Innername"
//a := new(Src)
////a.Inner = new(SrcInner)
//
//stime := time.Now().UnixNano()
//for i := 0; i < 1000000; i++ {
// err := structutils.Map2Struct(mapInstance, a)
// if err != nil {
// fmt.Println(err)
// }
//}
//etime := time.Now().UnixNano()
//fmt.Println(etime - stime)
//if err != nil {
// fmt.Println(err)
//} else {
// fmt.Println(a)
//}
s := new(Src)
//name, b := structutils.IndirectType(reflect.TypeOf(s)).FieldByName("Inner")
//if structutils.IndirectType(name.Type).Kind() != reflect.Struct {
// fmt.Println(name.Name + "不是结构体")
//} else {
// //innerType := name.Type
// innerValue := structutils.Indirect(reflect.ValueOf(s)).FieldByName("Inner")
// //if innerValue.IsValid() && innerValue.IsNil() {
// // innerValue.Set(reflect.New(innerValue.Type().Elem()))
// //}
// if !innerValue.IsValid() {
// fmt.Println("is valid")
// } else {
// //innerValue.Set(reflect.New(innerValue.Type()))
// fmt.Println(innerValue.CanSet())
// fmt.Println(innerValue.CanAddr())
// //mapstructure.Decode(innerMap, innerValue.Addr().Interface())
// }
//
//}
//
//fmt.Println(name, b)
//将 map 转换为指定的结构体
// if err := decode(mapInstance, &s); err != nil {
// fmt.Println(err)
// }
fmt.Printf("map2struct后得到的 struct 内容为:%v", s)
}
func getPrefixKeyMap(m map[string]interface{}) map[string]map[string]interface{} {
key2map := make(map[string]map[string]interface{})
for k, v := range m {
if !strings.Contains(k, ".") {
continue
}
lastIndex := strings.LastIndex(k, ".")
prefix := k[0:lastIndex]
m2 := key2map[prefix]
if m2 == nil {
key2map[prefix] = map[string]interface{}{k[lastIndex+1:]: v}
} else {
m2[k[lastIndex+1:]] = v
}
delete(m, k)
}
return key2map
}
func TestReflect(t *testing.T) {
type dog struct {
LegCount int
}
// 获取dog实例的反射值对象
valueOfDog := reflect.ValueOf(&dog{}).Elem()
// 获取legCount字段的值
vLegCount := valueOfDog.FieldByName("LegCount")
fmt.Println(vLegCount.CanSet())
fmt.Println(vLegCount.CanAddr())
// 尝试设置legCount的值(这里会发生崩溃)
vLegCount.SetInt(4)
}
func TestTemplateResolve(t *testing.T) {
d := make(map[string]string)
d["Name"] = "黄先生"
d["Age"] = "23jlfdsjf"
resolve := TemplateResolve("{{.Name}} is name, and {{.Age}} is age", d)
fmt.Println(resolve)
}

View File

@@ -0,0 +1,28 @@
package utils
import (
"bytes"
"text/template"
)
func parse(t *template.Template, vars interface{}) string {
var tmplBytes bytes.Buffer
err := t.Execute(&tmplBytes, vars)
if err != nil {
panic(err)
}
return tmplBytes.String()
}
// 模板字符串解析
// @param str 模板字符串
// @param vars 参数变量
func TemplateParse(str string, vars interface{}) string {
tmpl, err := template.New("tmpl").Parse(str)
if err != nil {
panic(err)
}
return parse(tmpl, vars)
}

View File

@@ -0,0 +1,74 @@
package utils
// ConvertToINodeArray 其他的结构体想要生成菜单树,直接实现这个接口
type INode interface {
// GetId获取id
GetId() int
// GetPid 获取父id
GetPid() int
// IsRoot 判断当前节点是否是顶层根节点
IsRoot() bool
SetChildren(childern interface{})
}
type INodes []INode
func (nodes INodes) Len() int {
return len(nodes)
}
func (nodes INodes) Swap(i, j int) {
nodes[i], nodes[j] = nodes[j], nodes[i]
}
func (nodes INodes) Less(i, j int) bool {
return nodes[i].GetId() < nodes[j].GetId()
}
// GenerateTree 自定义的结构体实现 INode 接口后调用此方法生成树结构
// nodes 需要生成树的节点
// selectedNode 生成树后选中的节点
// menuTrees 生成成功后的树结构对象
func GenerateTree(nodes []INode) (trees []INode) {
trees = []INode{}
// 定义顶层根和子节点
var roots, childs []INode
for _, v := range nodes {
if v.IsRoot() {
// 判断顶层根节点
roots = append(roots, v)
}
childs = append(childs, v)
}
for _, v := range roots {
// 递归
setChildren(v, childs)
trees = append(trees, v)
}
return
}
// recursiveTree 递归生成树结构
// tree 递归的树对象
// nodes 递归的节点
// selectedNodes 选中的节点
func setChildren(parent INode, nodes []INode) {
children := []INode{}
for _, v := range nodes {
if v.IsRoot() {
// 如果当前节点是顶层根节点就跳过
continue
}
if parent.GetId() == v.GetPid() {
children = append(children, v)
}
}
if len(children) == 0 {
return
}
parent.SetChildren(children)
for _, c := range children {
setChildren(c, nodes)
}
}

27
server/pkg/utils/yml.go Normal file
View File

@@ -0,0 +1,27 @@
package utils
import (
"errors"
"io/ioutil"
"gopkg.in/yaml.v3"
)
// 从指定路径加载yaml文件
func LoadYml(path string, out interface{}) error {
yamlFileBytes, readErr := ioutil.ReadFile(path)
if readErr != nil {
return readErr
}
// yaml解析
err := yaml.Unmarshal(yamlFileBytes, out)
if err != nil {
return errors.New("无法解析 [" + path + "] -- " + err.Error())
}
return nil
}
func LoadYmlByString(yamlStr string, out interface{}) error {
// yaml解析
return yaml.Unmarshal([]byte(yamlStr), out)
}