feat: export RawEngine api

This commit is contained in:
Young Xu 2023-03-22 21:41:03 +08:00
parent 7336d0d9d2
commit 0b17bf0e71
Signed by: xuthus5
GPG Key ID: A23CF9620CBB55F9
12 changed files with 717 additions and 9 deletions

View File

@ -144,6 +144,11 @@ func (r *Register) PreRun(f func() error) error {
return f()
}
// RawEngine 获取gin路由引擎
func (r *Register) RawEngine() *gin.Engine {
return r.engine
}
// Run 服务运行
func (r *Register) Run() {
if r.addr == "" {

View File

@ -26,14 +26,10 @@ func TestRegister_getCallFunc(t *testing.T) {
}
func TestNewRegister(t *testing.T) {
var reg = NewRegister()
reg.DefaultRouter(WithGinMode(gin.DebugMode))
if err := reg.PreRun(func() error {
return nil
}); err != nil {
// todo
}
var register = NewRegister()
register.DefaultRouter(WithListenAddress(""), WithGinMode(gin.ReleaseMode), WithCors(), WithRecovery())
register.PreRun(nil)
// protoc core/file_module.proto --coco_out=core --go_out=core
//reg.RegisterStruct(AutoGenFileRouterMap, &File{})
reg.Run()
//reg.RegisterStruct(AutoGenXXXRouterMap, &XXX{})
register.Run()
}

24
utils/alg.go Normal file
View File

@ -0,0 +1,24 @@
package utils
import "math"
// DivisionRoundingUp 除法a/b向上取整
func DivisionRoundingUp(a, b int64) int64 {
fa := float64(a)
fb := float64(b)
return int64(math.Ceil(fa / fb))
}
// DivisionRoundingDown 除法a/b向下取整
func DivisionRoundingDown(a, b int64) int64 {
fa := float64(a)
fb := float64(b)
return int64(math.Floor(fa / fb))
}
// DivisionRounding 除法a/b四舍五入
func DivisionRounding(a, b int64) int64 {
fa := float64(a)
fb := float64(b)
return int64(math.Floor((fa / fb) + 0.5))
}

10
utils/alg_test.go Normal file
View File

@ -0,0 +1,10 @@
package utils
import (
"fmt"
"testing"
)
func TestDivisionRounding(t *testing.T) {
fmt.Println(DivisionRounding(100, 9))
}

221
utils/array.go Normal file
View File

@ -0,0 +1,221 @@
package utils
import (
"errors"
"fmt"
"reflect"
)
// PluckUint64 从一个struct list 中 抽出某uint64字段的slice
func PluckUint64(list interface{}, fieldName string) []uint64 {
var result []uint64
vo := reflect.ValueOf(list)
switch vo.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < vo.Len(); i++ {
elem := vo.Index(i)
for elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
err := errors.New("element not struct")
panic(err)
}
f := elem.FieldByName(fieldName)
if !f.IsValid() {
err := fmt.Errorf("struct missed field %s", fieldName)
panic(err)
}
if f.Kind() != reflect.Uint64 {
err := fmt.Errorf("struct element %s type required uint64", fieldName)
panic(err)
}
result = append(result, f.Uint())
}
default:
err := errors.New("required list of struct type")
panic(err)
}
return result
}
// PluckUint64Map 从一个struct list 中 抽出某uint64字段的map
func PluckUint64Map(list interface{}, fieldName string) map[uint64]bool {
out := PluckUint64(list, fieldName)
res := map[uint64]bool{}
for _, v := range out {
res[v] = true
}
return res
}
func PluckUint32(list interface{}, fieldName string) []uint32 {
var result []uint32
vo := reflect.ValueOf(list)
switch vo.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < vo.Len(); i++ {
elem := vo.Index(i)
for elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
err := errors.New("element not struct")
panic(err)
}
f := elem.FieldByName(fieldName)
if !f.IsValid() {
err := fmt.Errorf("struct missed field %s", fieldName)
panic(err)
}
if f.Kind() != reflect.Uint32 {
err := fmt.Errorf("struct element %s type required uint32", fieldName)
panic(err)
}
result = append(result, uint32(f.Uint()))
}
default:
err := errors.New("required list of struct type")
panic(err)
}
return result
}
func PluckUint32Map(list interface{}, fieldName string) map[uint32]bool {
out := PluckUint32(list, fieldName)
res := map[uint32]bool{}
for _, v := range out {
res[v] = true
}
return res
}
// PluckString 从一个struct list 中 抽出某string字段的slice
func PluckString(list interface{}, fieldName string) []string {
var result []string
vo := reflect.ValueOf(list)
switch vo.Kind() {
case reflect.Array, reflect.Slice:
for i := 0; i < vo.Len(); i++ {
elem := vo.Index(i)
for elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
err := errors.New("element not struct")
panic(err)
}
f := elem.FieldByName(fieldName)
if !f.IsValid() {
err := fmt.Errorf("struct missed field %s", fieldName)
panic(err)
}
if f.Kind() != reflect.String {
err := fmt.Errorf("struct element %s type required string", fieldName)
panic(err)
}
result = append(result, f.String())
}
default:
err := errors.New("required list of struct type")
panic(err)
}
return result
}
func PluckStringMap(list interface{}, fieldName string) map[string]bool {
out := PluckString(list, fieldName)
res := map[string]bool{}
for _, v := range out {
res[v] = true
}
return res
}
// KeyByMap 从一个struct list 中 根据某字段 转成一个以该字段为key的map
// list 是 []StructType
// res 是 *map[fieldType]StructType
func KeyByMap(list interface{}, fieldName string, res interface{}) {
// 取下 field type
vo := EnsureIsSliceOrArray(list)
elType := vo.Type().Elem()
t := elType
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
panic(fmt.Sprintf("slice or array element required struct type, but got %v", t))
}
var keyType reflect.Type
if sf, ok := t.FieldByName(fieldName); ok {
keyType = sf.Type
} else {
panic(fmt.Sprintf("not found field %s", fieldName))
}
m := reflect.MakeMap(reflect.MapOf(keyType, elType))
resVo := reflect.ValueOf(res)
if resVo.Kind() != reflect.Ptr {
panic(fmt.Sprintf("invalid res type %v, required *map[key]val", resVo.Type()))
}
resVo = resVo.Elem()
EnsureIsMapType(resVo, keyType, elType)
l := vo.Len()
for i := 0; i < l; i++ {
el := vo.Index(i)
elDef := el
for elDef.Kind() == reflect.Ptr {
elDef = elDef.Elem()
}
f := elDef.FieldByName(fieldName)
if !f.IsValid() {
continue
}
m.SetMapIndex(f, el)
}
resVo.Set(m)
}
// 基本数据类型的判断是否在数组内是则返回true以及下标
func BaseTypeInArray(val interface{}, array interface{}) (exists bool, index int) {
exists = false
index = -1
switch reflect.TypeOf(array).Kind() {
case reflect.Slice:
s := reflect.ValueOf(array)
length := s.Len()
for i := 0; i < length; i++ {
if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
index = i
exists = true
return
}
}
}
return
}

50
utils/array_test.go Normal file
View File

@ -0,0 +1,50 @@
package utils
import (
log "github.com/sirupsen/logrus"
"testing"
)
func TestPluck(t *testing.T) {
type S struct {
Id uint64
}
arr := []S{
{
Id: 1,
},
{
Id: 2,
},
}
out := PluckUint64(arr, "Id")
log.Infof("out %+v", out)
out = PluckUint64("", "Id")
log.Infof("out %+v", out)
}
func TestKeyBy(t *testing.T) {
type T struct {
Id uint32
Name string
}
list := []T{
{
Id: 1,
Name: "hello",
},
{
Id: 2,
Name: "world",
},
}
var m map[uint32]T
KeyByMap(list, "Id", &m)
log.Infof("m is %+v", m)
}

174
utils/reflect.go Normal file
View File

@ -0,0 +1,174 @@
package utils
import (
"fmt"
log "github.com/sirupsen/logrus"
"reflect"
"strings"
)
func ReflectGet(obj interface{}, path string, failHint *string) (res interface{}, success bool) {
setFailHint := func(hint string) {
if failHint != nil {
*failHint = hint
}
}
for obj != nil && path != "" {
v := reflect.ValueOf(obj)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
setFailHint("not struct type")
break
}
var fieldName string
pos := strings.IndexByte(path, '.')
if pos < 0 {
fieldName = path
path = ""
} else {
fieldName = path[:pos]
path = path[pos+1:]
}
f := v.FieldByName(fieldName)
if !f.IsValid() {
setFailHint(fmt.Sprintf("%s not found", fieldName))
break
}
if path == "" {
res = f.Interface()
success = true
break
}
obj = f.Interface()
}
return
}
func ReflectGetInt(obj interface{}, path string, failHint *string) (res int, success bool) {
setFailHint := func(hint string) {
if failHint != nil {
*failHint = hint
}
}
var i interface{}
i, success = ReflectGet(obj, path, failHint)
if !success {
return
}
switch v := i.(type) {
case int:
res = v
success = true
case int32:
res = int(v)
success = true
default:
setFailHint(fmt.Sprintf("type not match: %s", reflect.TypeOf(i).String()))
}
return
}
func ReflectGetStr(obj interface{}, path string, failHint *string) (res string, success bool) {
setFailHint := func(hint string) {
if failHint != nil {
*failHint = hint
}
}
var i interface{}
i, success = ReflectGet(obj, path, failHint)
if !success {
return
}
switch v := i.(type) {
case string:
res = v
success = true
case []byte:
res = string(v)
success = true
default:
setFailHint(fmt.Sprintf("type not match: %s", reflect.TypeOf(i).String()))
}
return
}
func Interface2Int(i interface{}) int {
vo := reflect.ValueOf(i)
vk := vo.Kind()
switch vk {
case reflect.Uint, reflect.Uint32, reflect.Uint64, reflect.Uint8, reflect.Uint16:
return int(vo.Uint())
}
return int(vo.Int())
}
func Interface2String(i interface{}) string {
vo := reflect.ValueOf(i)
if vo.Kind() != reflect.String {
log.Infof("expected string type, but got %v", vo.Type())
panic("expected string type")
}
return vo.String()
}
func EnsureIsSliceOrArray(obj interface{}) (res reflect.Value) {
vo := reflect.ValueOf(obj)
for vo.Kind() == reflect.Ptr || vo.Kind() == reflect.Interface {
vo = vo.Elem()
}
k := vo.Kind()
if k != reflect.Slice && k != reflect.Array {
panic(fmt.Sprintf("obj required slice or array type, but got %v", vo.Type()))
}
res = vo
return
}
func EnsureIsMapType(m reflect.Value, keyType, valType reflect.Type) {
if m.Kind() != reflect.Map {
panic(fmt.Sprintf("required map type, but got %v", m.Type()))
}
t := m.Type()
if t.Key() != keyType {
panic(fmt.Sprintf("map key type not equal, %v != %v", t.Key(), keyType))
}
if t.Elem() != valType {
panic(fmt.Sprintf("map val type not equal, %v != %v", t.Elem(), valType))
}
}
func ClearSlice(ptr interface{}) {
vo := reflect.ValueOf(ptr)
if vo.Kind() != reflect.Ptr {
panic("required ptr to slice type")
}
for vo.Kind() == reflect.Ptr {
vo = vo.Elem()
}
if vo.Kind() != reflect.Slice {
panic("required ptr to slice type")
}
vo.Set(reflect.MakeSlice(vo.Type(), 0, 0))
}
func GetSliceLen(i interface{}) int {
vo := reflect.ValueOf(i)
for vo.Kind() == reflect.Ptr {
vo = vo.Elem()
}
if vo.Kind() != reflect.Slice && vo.Kind() != reflect.Array {
panic("required slice or array type")
}
return vo.Len()
}

54
utils/reflect_test.go Normal file
View File

@ -0,0 +1,54 @@
package utils
import (
log "github.com/sirupsen/logrus"
"testing"
)
type A struct {
I int
}
type B struct {
AA *A
}
func TestReflectGetInt(t *testing.T) {
var b B
b.AA = &A{}
b.AA.I = 10
var h string
i, success := ReflectGetInt(&b, "AA.I", &h)
if success {
log.Infof("got %d", i)
} else {
log.Warnf("get fail %s", h)
}
}
func TestInterface2Int(t *testing.T) {
i := Interface2Int(int64(-10))
log.Infof("i %d", i)
}
func TestReflectGetStr(t *testing.T) {
var typ = &struct {
A string
B uint64
}{
A: "hello",
B: 100,
}
var c interface{} = typ
res, _ := ReflectGetStr(c, "A", nil)
log.Infof(res)
}
func TestClearSlicePtr(t *testing.T) {
l := []int{1, 2, 3}
p := &l
ClearSlice(&p)
}

18
utils/time.go Normal file
View File

@ -0,0 +1,18 @@
package utils
import "time"
// GetTimeNowUnix 获取当前时间的标准时间戳
func GetTimeNowUnix() int64 {
return time.Now().Unix()
}
// GetTimeNowUnixMilli 获取当前时间的毫秒时间戳
func GetTimeNowUnixMilli() int64 {
return time.Now().UnixNano() / 1e6
}
// UnixMilli2Time 毫秒时间戳转 time.Time 结构
func UnixMilli2Time(u int64) time.Time {
return time.Unix(u/1e3, 0)
}

14
utils/time_test.go Normal file
View File

@ -0,0 +1,14 @@
package utils
import (
"fmt"
"testing"
)
func TestGetTimeNowMillisecond(t *testing.T) {
fmt.Println(GetTimeNowUnixMilli())
}
func TestUnixMilli2Time(t *testing.T) {
fmt.Println(UnixMilli2Time(1631693848445).Unix())
}

102
utils/url.go Normal file
View File

@ -0,0 +1,102 @@
package utils
import (
"fmt"
"net/url"
"reflect"
"strings"
)
// Struct2UrlValues 将struct转为 url.Values 结构 只操作第一层 不嵌套
// 如果有json标签 将依照json标签作为key 否则按照字段名做key
// 如果struct字段为空 依然会将空值写入 url.Values 中
func Struct2UrlValues(obj interface{}) url.Values {
if obj == nil {
panic("object is nil")
}
var u = url.Values{}
vo := reflect.ValueOf(obj)
to := reflect.TypeOf(obj)
if vo.Kind() == reflect.Ptr {
vo = vo.Elem()
}
if to.Kind() == reflect.Ptr {
to = to.Elem()
}
for i := 0; i < vo.NumField(); i++ {
fieldType := to.Field(i)
if fieldType.PkgPath != "" {
continue
}
fieldName := fieldType.Name
fieldTag := fieldType.Tag.Get("json")
if fieldTag != "" {
fieldName = strings.Replace(fieldTag, ",omitempty", "", 1)
}
fieldValue := vo.Field(i)
if fieldValue.Kind() == reflect.Ptr || fieldValue.Kind() == reflect.Struct ||
fieldValue.Kind() == reflect.Map || fieldValue.Kind() == reflect.Slice ||
fieldValue.Kind() == reflect.Array || fieldValue.Kind() == reflect.Chan ||
fieldValue.Kind() == reflect.Func || fieldValue.Kind() == reflect.Interface ||
fieldValue.Kind() == reflect.Complex64 || fieldValue.Kind() == reflect.Complex128 ||
fieldValue.Kind() == reflect.Invalid || fieldValue.Kind() == reflect.Uintptr ||
fieldValue.Kind() == reflect.UnsafePointer {
continue
}
v := fmt.Sprintf("%+v", fieldValue.Interface())
u.Set(fieldName, v)
}
return u
}
// Struct2UrlValuesOmitEmpty Struct2UrlValues 忽略空值字段
func Struct2UrlValuesOmitEmpty(obj interface{}) url.Values {
if obj == nil {
panic("object is nil")
}
var u = url.Values{}
vo := reflect.ValueOf(obj)
to := reflect.TypeOf(obj)
if vo.Kind() == reflect.Ptr {
vo = vo.Elem()
}
if to.Kind() == reflect.Ptr {
to = to.Elem()
}
for i := 0; i < vo.NumField(); i++ {
fieldType := to.Field(i)
if fieldType.PkgPath != "" {
continue
}
fieldName := fieldType.Name
fieldTag := fieldType.Tag.Get("json")
if fieldTag != "" {
fieldName = strings.Replace(fieldTag, ",omitempty", "", 1)
}
fieldValue := vo.Field(i)
if fieldValue.Kind() == reflect.Ptr || fieldValue.Kind() == reflect.Struct ||
fieldValue.Kind() == reflect.Map || fieldValue.Kind() == reflect.Slice ||
fieldValue.Kind() == reflect.Array || fieldValue.Kind() == reflect.Chan ||
fieldValue.Kind() == reflect.Func || fieldValue.Kind() == reflect.Interface ||
fieldValue.Kind() == reflect.Complex64 || fieldValue.Kind() == reflect.Complex128 ||
fieldValue.Kind() == reflect.Invalid || fieldValue.Kind() == reflect.Uintptr ||
fieldValue.Kind() == reflect.UnsafePointer {
continue
}
if fieldValue.IsZero() {
continue
}
v := fmt.Sprintf("%+v", fieldValue.Interface())
u.Set(fieldName, v)
}
return u
}

40
utils/url_test.go Normal file
View File

@ -0,0 +1,40 @@
package utils
import (
"fmt"
"testing"
)
func TestStruct2UrlValues(t *testing.T) {
type A struct {
AccountType int32 `protobuf:"varint,1,opt,name=accountType,proto3" json:"accountType,omitempty"` // 用户账号类型 2微信开放账号
Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` // 微信用户则填入对应的 openid/unionid
UserIp string `protobuf:"bytes,3,opt,name=userIp,proto3" json:"userIp,omitempty"` // 用户领取奖励时的真实外网 IP
PostTime int64 `protobuf:"varint,4,opt,name=postTime,proto3" json:"postTime,omitempty"` // 用户操作时间戳单位秒格林威治时间精确到秒如1501590972
WxSubType int32 `protobuf:"varint,5,opt,name=wxSubType,proto3" json:"wxSubType,omitempty"` // 1微信公众号 2微信小程序。
WxToken string `protobuf:"bytes,6,opt,name=wxToken,proto3" json:"wxToken,omitempty"` // wxSubType = 1微信公众号或第三方登录则为授权的 access_token
AppId string `protobuf:"bytes,7,opt,name=appId,proto3" json:"appId,omitempty"` // 天御appId
RandNum string `protobuf:"bytes,8,opt,name=randNum,proto3" json:"randNum,omitempty"` // 随机数
}
var a = A{}
u := Struct2UrlValues(a)
fmt.Println(u.Encode())
}
func TestStruct2UrlValuesOmitEmpty(t *testing.T) {
type A struct {
AccountType int32 `protobuf:"varint,1,opt,name=accountType,proto3" json:"accountType,omitempty"` // 用户账号类型 2微信开放账号
Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` // 微信用户则填入对应的 openid/unionid
UserIp string `protobuf:"bytes,3,opt,name=userIp,proto3" json:"userIp,omitempty"` // 用户领取奖励时的真实外网 IP
PostTime int64 `protobuf:"varint,4,opt,name=postTime,proto3" json:"postTime,omitempty"` // 用户操作时间戳单位秒格林威治时间精确到秒如1501590972
WxSubType int32 `protobuf:"varint,5,opt,name=wxSubType,proto3" json:"wxSubType,omitempty"` // 1微信公众号 2微信小程序。
WxToken string `protobuf:"bytes,6,opt,name=wxToken,proto3" json:"wxToken,omitempty"` // wxSubType = 1微信公众号或第三方登录则为授权的 access_token
AppId string `protobuf:"bytes,7,opt,name=appId,proto3" json:"appId,omitempty"` // 天御appId
RandNum string `protobuf:"bytes,8,opt,name=randNum,proto3" json:"randNum,omitempty"` // 随机数
}
var a = A{}
u := Struct2UrlValuesOmitEmpty(a)
fmt.Println(u.Encode())
}