mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
feat: sql解析器替换、工单统一由‘我的流程’发起、流程定义支持自定义条件触发审批、资源隐藏编号、model支持物理删除等
This commit is contained in:
@@ -4,7 +4,7 @@ import "fmt"
|
||||
|
||||
const (
|
||||
AppName = "mayfly-go"
|
||||
Version = "v1.8.8"
|
||||
Version = "v1.8.9"
|
||||
)
|
||||
|
||||
func GetAppInfo() string {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 伪删除之未删除过滤条件
|
||||
// 伪删除之伪删除过滤条件
|
||||
func UndeleteScope(db *gorm.DB) *gorm.DB {
|
||||
return db.Where(model.DeletedColumn, model.ModelUndeleted)
|
||||
}
|
||||
@@ -17,30 +17,29 @@ func UndeleteScope(db *gorm.DB) *gorm.DB {
|
||||
// 根据id获取实体对象。model需为指针类型(需要将查询出来的值赋值给model)
|
||||
//
|
||||
// 若error不为nil则为不存在该记录
|
||||
// @param modelP 数据库映射实体模型
|
||||
func GetById(dbModel any, id uint64, cols ...string) error {
|
||||
return NewQuery(dbModel, model.NewCond().Columns(cols...).Eq(model.IdColumn, id)).GenGdb().Scopes(UndeleteScope).First(dbModel).Error
|
||||
// @param dbModel 数据库映射实体模型
|
||||
func GetById(dbModel model.ModelI, id uint64, cols ...string) error {
|
||||
return NewQuery(dbModel, model.NewCond().Columns(cols...).Eq(model.IdColumn, id)).GenGdb().First(dbModel).Error
|
||||
}
|
||||
|
||||
// 根据model获取单个实体对象
|
||||
//
|
||||
// 若 error不为nil,则为不存在该记录
|
||||
// @param cond 查询条件
|
||||
func GetByCond(dbModel any, cond *model.QueryCond) error {
|
||||
return NewQuery(dbModel, cond).GenGdb().Scopes(UndeleteScope).First(cond.GetDest()).Error
|
||||
func GetByCond(dbModel model.ModelI, cond *model.QueryCond) error {
|
||||
return NewQuery(dbModel, cond).GenGdb().First(cond.GetDest()).Error
|
||||
}
|
||||
|
||||
// 根据条件cond获取指定model表统计数量
|
||||
func CountByCond(dbModel any, cond *model.QueryCond) int64 {
|
||||
func CountByCond(dbModel model.ModelI, cond *model.QueryCond) int64 {
|
||||
var count int64
|
||||
NewQuery(dbModel, cond).GenGdb().Scopes(UndeleteScope).Count(&count)
|
||||
NewQuery(dbModel, cond).GenGdb().Count(&count)
|
||||
return count
|
||||
}
|
||||
|
||||
// PageQuery 根据查询条件分页查询数据
|
||||
// PageQuery 根据查询条件分页查询数据,若需要伪删除过滤,则自行过滤-调用q.Undeleted()
|
||||
// 若未指定查询列,则查询列以toModels字段为准
|
||||
func PageQuery[T any](q *Query, pageParam *model.PageParam, toModels T) (*model.PageResult[T], error) {
|
||||
q.Undeleted()
|
||||
gdb := q.GenGdb()
|
||||
var count int64
|
||||
err := gdb.Count(&count).Error
|
||||
@@ -61,13 +60,13 @@ func PageQuery[T any](q *Query, pageParam *model.PageParam, toModels T) (*model.
|
||||
}
|
||||
|
||||
// PageByCond 根据指定查询条件分页查询数据
|
||||
func PageByCond[T any](dbModel any, cond *model.QueryCond, pageParam *model.PageParam, toModels T) (*model.PageResult[T], error) {
|
||||
func PageByCond[T any](dbModel model.ModelI, cond *model.QueryCond, pageParam *model.PageParam, toModels T) (*model.PageResult[T], error) {
|
||||
return PageQuery(NewQuery(dbModel, cond), pageParam, toModels)
|
||||
}
|
||||
|
||||
// SelectByCond 根据条件查询结果集
|
||||
func SelectByCond(dbModel any, cond *model.QueryCond) error {
|
||||
return NewQuery(dbModel, cond).GenGdb().Scopes(UndeleteScope).Find(cond.GetDest()).Error
|
||||
func SelectByCond(dbModel model.ModelI, cond *model.QueryCond) error {
|
||||
return NewQuery(dbModel, cond).GenGdb().Find(cond.GetDest()).Error
|
||||
}
|
||||
|
||||
// SelectBySql 根据sql查询数据
|
||||
@@ -81,43 +80,43 @@ func ExecSql(sql string, params ...any) error {
|
||||
|
||||
// 插入model
|
||||
// @param model 数据库映射实体模型
|
||||
func Insert(model any) error {
|
||||
func Insert(model model.ModelI) error {
|
||||
return InsertWithDb(global.Db, model)
|
||||
}
|
||||
|
||||
// 使用指定gormDb插入model
|
||||
func InsertWithDb(db *gorm.DB, model any) error {
|
||||
func InsertWithDb(db *gorm.DB, model model.ModelI) error {
|
||||
return db.Create(model).Error
|
||||
}
|
||||
|
||||
// 批量插入
|
||||
func BatchInsert[T any](models []T) error {
|
||||
func BatchInsert[T model.ModelI](models []T) error {
|
||||
return BatchInsertWithDb[T](global.Db, models)
|
||||
}
|
||||
|
||||
// 批量插入
|
||||
func BatchInsertWithDb[T any](db *gorm.DB, models []T) error {
|
||||
func BatchInsertWithDb[T model.ModelI](db *gorm.DB, models []T) error {
|
||||
return db.CreateInBatches(models, len(models)).Error
|
||||
}
|
||||
|
||||
// 根据id更新model,更新字段为model中不为空的值,即int类型不为0,ptr类型不为nil这类字段值
|
||||
// @param model 数据库映射实体模型
|
||||
func UpdateById(model any, columns ...string) error {
|
||||
func UpdateById(model model.ModelI, columns ...string) error {
|
||||
return UpdateByIdWithDb(global.Db, model, columns...)
|
||||
}
|
||||
|
||||
func UpdateByIdWithDb(db *gorm.DB, model any, columns ...string) error {
|
||||
func UpdateByIdWithDb(db *gorm.DB, model model.ModelI, columns ...string) error {
|
||||
return db.Model(model).Select(columns).Updates(model).Error
|
||||
}
|
||||
|
||||
// UpdateByCondWithDb 使用指定gorm.DB更新满足条件的数据(model的主键值需为空,否则会带上主键条件)
|
||||
func UpdateByCond(dbModel any, values any, cond *model.QueryCond) error {
|
||||
func UpdateByCond(dbModel model.ModelI, values any, cond *model.QueryCond) error {
|
||||
return UpdateByCondWithDb(global.Db, dbModel, values, cond)
|
||||
}
|
||||
|
||||
// UpdateByCondWithDb 使用指定gorm.DB更新满足条件的数据(model的主键值需为空,否则会带上主键条件)
|
||||
// @values values must be a struct or map.
|
||||
func UpdateByCondWithDb(db *gorm.DB, dbModel any, values any, cond *model.QueryCond) error {
|
||||
func UpdateByCondWithDb(db *gorm.DB, dbModel model.ModelI, values any, cond *model.QueryCond) error {
|
||||
gormDb := db.Model(dbModel).Select(cond.GetSelectColumns())
|
||||
setGdbWhere(gormDb, cond)
|
||||
return gormDb.Updates(values).Error
|
||||
@@ -125,12 +124,12 @@ func UpdateByCondWithDb(db *gorm.DB, dbModel any, values any, cond *model.QueryC
|
||||
|
||||
// 根据id删除model
|
||||
// @param model 数据库映射实体模型
|
||||
func DeleteById(model_ any, id ...uint64) error {
|
||||
func DeleteById(model_ model.ModelI, id ...uint64) error {
|
||||
return DeleteByIdWithDb(global.Db, model_, id...)
|
||||
}
|
||||
|
||||
// 根据id使用指定gromDb删除
|
||||
func DeleteByIdWithDb(db *gorm.DB, model_ any, id ...uint64) error {
|
||||
func DeleteByIdWithDb(db *gorm.DB, model_ model.ModelI, id ...uint64) error {
|
||||
return DeleteByCondWithDb(db, model_, model.NewCond().In(model.IdColumn, id))
|
||||
}
|
||||
|
||||
@@ -138,7 +137,7 @@ func DeleteByIdWithDb(db *gorm.DB, model_ any, id ...uint64) error {
|
||||
//
|
||||
// @param dbModel 数据库映射实体模型
|
||||
// @param cond 条件
|
||||
func DeleteByCond(dbModel any, cond *model.QueryCond) error {
|
||||
func DeleteByCond(dbModel model.ModelI, cond *model.QueryCond) error {
|
||||
return DeleteByCondWithDb(global.Db, dbModel, cond)
|
||||
}
|
||||
|
||||
@@ -146,8 +145,12 @@ func DeleteByCond(dbModel any, cond *model.QueryCond) error {
|
||||
//
|
||||
// @param dbModel 数据库映射实体模型
|
||||
// @param cond 条件
|
||||
func DeleteByCondWithDb(db *gorm.DB, dbModel any, cond *model.QueryCond) error {
|
||||
return setGdbWhere(db.Model(dbModel), cond).Updates(getDeleteColumnValue()).Error
|
||||
func DeleteByCondWithDb(db *gorm.DB, dbModel model.ModelI, cond *model.QueryCond) error {
|
||||
gdb := setGdbWhere(db.Model(dbModel), cond)
|
||||
if !dbModel.LogicDelete() {
|
||||
return gdb.Delete(dbModel).Error
|
||||
}
|
||||
return gdb.Updates(getDeleteColumnValue()).Error
|
||||
}
|
||||
|
||||
func getDeleteColumnValue() map[string]any {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type Query struct {
|
||||
dbModel any // 数据库模型
|
||||
dbModel model.ModelI // 数据库模型
|
||||
table string
|
||||
joins string // join 类似 left join emails on emails.user_id = users.id
|
||||
|
||||
@@ -17,8 +17,13 @@ type Query struct {
|
||||
}
|
||||
|
||||
// NewQuery 构建查询条件
|
||||
func NewQuery(dbModel any, cond *model.QueryCond) *Query {
|
||||
return &Query{dbModel: dbModel, cond: cond}
|
||||
func NewQuery(dbModel model.ModelI, cond *model.QueryCond) *Query {
|
||||
q := &Query{dbModel: dbModel, cond: cond}
|
||||
// 如果是逻辑删除,默认加上伪删除过滤条件
|
||||
if dbModel.LogicDelete() {
|
||||
q.Undeleted()
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func NewQueryWithTableName(tableName string) *Query {
|
||||
@@ -84,5 +89,6 @@ func setGdbWhere(gdb *gorm.DB, cond *model.QueryCond) *gorm.DB {
|
||||
for i, v := range cond.GetWheres() {
|
||||
gdb.Where(i, v...)
|
||||
}
|
||||
|
||||
return gdb
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func DebugWithFields(ctx context.Context, msg string, mapFields map[string]any)
|
||||
|
||||
// debug记录,并将堆栈信息添加至msg里,默认记录10个堆栈信息
|
||||
func DebugTrace(msg string, err error) {
|
||||
Log(context.Background(), slog.LevelDebug, fmt.Sprintf(msg+" %s\n%s", err.Error(), runtimex.StatckStr(2, 10)))
|
||||
Log(context.Background(), slog.LevelDebug, fmt.Sprintf(msg+" %s\n%s", err.Error(), runtimex.StackStr(2, 10)))
|
||||
}
|
||||
|
||||
func Info(msg string, args ...any) {
|
||||
@@ -132,7 +132,7 @@ func ErrorTrace(msg string, err any) {
|
||||
default:
|
||||
errMsg = fmt.Sprintf("%v", t)
|
||||
}
|
||||
Log(context.Background(), slog.LevelError, fmt.Sprintf(msg+"\n%s\n%s", errMsg, runtimex.StatckStr(2, 20)))
|
||||
Log(context.Background(), slog.LevelError, fmt.Sprintf(msg+"\n%s\n%s", errMsg, runtimex.StackStr(2, 20)))
|
||||
}
|
||||
|
||||
func ErrorWithFields(ctx context.Context, msg string, mapFields map[string]any) {
|
||||
|
||||
@@ -5,3 +5,7 @@ type LoginAccount struct {
|
||||
Username string
|
||||
Token string
|
||||
}
|
||||
|
||||
func (la *LoginAccount) GetAesKey() string {
|
||||
return la.Token[:24]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/may-fly/cast"
|
||||
)
|
||||
|
||||
type IdGenType int
|
||||
@@ -35,6 +37,9 @@ type ModelI interface {
|
||||
//
|
||||
// 如创建时间,修改时间,创建者,修改者信息等
|
||||
FillBaseInfo(idGenType IdGenType, account *LoginAccount)
|
||||
|
||||
// LogicDelete 是否为逻辑删除
|
||||
LogicDelete() bool
|
||||
}
|
||||
|
||||
type IdModel struct {
|
||||
@@ -57,6 +62,10 @@ func (m *IdModel) FillBaseInfo(idGenType IdGenType, account *LoginAccount) {
|
||||
m.SetId(GetIdByGenType(idGenType))
|
||||
}
|
||||
|
||||
func (m *IdModel) LogicDelete() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 含有删除字段模型
|
||||
type DeletedModel struct {
|
||||
IdModel
|
||||
@@ -71,6 +80,32 @@ func (m *DeletedModel) FillBaseInfo(idGenType IdGenType, account *LoginAccount)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *DeletedModel) LogicDelete() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// CreateModelNLD 含有创建等信息,但不包含逻辑删除信息
|
||||
type CreateModelNLD struct {
|
||||
IdModel
|
||||
CreateTime *time.Time `json:"createTime"`
|
||||
CreatorId uint64 `json:"creatorId"`
|
||||
Creator string `json:"creator"`
|
||||
}
|
||||
|
||||
func (m *CreateModelNLD) FillBaseInfo(idGenType IdGenType, account *LoginAccount) {
|
||||
if !m.IsCreate() {
|
||||
return
|
||||
}
|
||||
|
||||
m.IdModel.FillBaseInfo(idGenType, account)
|
||||
nowTime := time.Now()
|
||||
m.CreateTime = &nowTime
|
||||
if account != nil {
|
||||
m.CreatorId = account.Id
|
||||
m.Creator = account.Username
|
||||
}
|
||||
}
|
||||
|
||||
// 含有删除、创建字段模型
|
||||
type CreateModel struct {
|
||||
DeletedModel
|
||||
@@ -93,6 +128,38 @@ func (m *CreateModel) FillBaseInfo(idGenType IdGenType, account *LoginAccount) {
|
||||
}
|
||||
}
|
||||
|
||||
// 基础实体模型,数据表最基础字段,不包含逻辑删除
|
||||
type ModelNLD struct {
|
||||
CreateModelNLD
|
||||
|
||||
UpdateTime *time.Time `json:"updateTime"`
|
||||
ModifierId uint64 `json:"modifierId"`
|
||||
Modifier string `json:"modifier"`
|
||||
}
|
||||
|
||||
// 设置基础信息. 如创建时间,修改时间,创建者,修改者信息
|
||||
func (m *ModelNLD) FillBaseInfo(idGenType IdGenType, account *LoginAccount) {
|
||||
nowTime := time.Now()
|
||||
isCreate := m.IsCreate()
|
||||
if isCreate {
|
||||
m.CreateTime = &nowTime
|
||||
m.IdModel.FillBaseInfo(idGenType, account)
|
||||
}
|
||||
m.UpdateTime = &nowTime
|
||||
|
||||
if account == nil {
|
||||
return
|
||||
}
|
||||
id := account.Id
|
||||
name := account.Username
|
||||
if isCreate {
|
||||
m.CreatorId = id
|
||||
m.Creator = name
|
||||
}
|
||||
m.Modifier = name
|
||||
m.ModifierId = id
|
||||
}
|
||||
|
||||
// 基础实体模型,数据表最基础字段,尽量每张表都包含这些字段
|
||||
type Model struct {
|
||||
CreateModel
|
||||
@@ -153,3 +220,25 @@ func (s *Slice[T]) Scan(value any) error {
|
||||
func (s Slice[T]) Value() (driver.Value, error) {
|
||||
return json.Marshal(s)
|
||||
}
|
||||
|
||||
// 带有额外其他信息字段的结构体
|
||||
type ExtraData struct {
|
||||
Extra Map[string, any] `json:"extra"`
|
||||
}
|
||||
|
||||
// SetExtraValue 设置额外信息字段值
|
||||
func (m *ExtraData) SetExtraValue(key string, val any) {
|
||||
if m.Extra != nil {
|
||||
m.Extra[key] = val
|
||||
} else {
|
||||
m.Extra = Map[string, any]{key: val}
|
||||
}
|
||||
}
|
||||
|
||||
// GetExtraString 获取额外信息中的string类型字段值
|
||||
func (e ExtraData) GetExtraString(key string) string {
|
||||
if e.Extra == nil {
|
||||
return ""
|
||||
}
|
||||
return cast.ToString(e.Extra[key])
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ type QueryCond struct {
|
||||
selectColumns []string // 查询的列信息
|
||||
condModel any // 条件模型
|
||||
|
||||
wheres map[string][]any
|
||||
wheres map[string][]any
|
||||
|
||||
orderBy []string
|
||||
|
||||
dest any // 结果集指针
|
||||
@@ -120,11 +121,11 @@ func (q *QueryCond) Le(column string, val any) *QueryCond {
|
||||
}
|
||||
|
||||
// And条件
|
||||
func (q *QueryCond) And(column string, val ...any) *QueryCond {
|
||||
func (q *QueryCond) And(columnOrQuery string, val ...any) *QueryCond {
|
||||
if q.wheres == nil {
|
||||
q.wheres = make(map[string][]any)
|
||||
}
|
||||
q.wheres[column] = val
|
||||
q.wheres[columnOrQuery] = val
|
||||
return q
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func LogHandler(rc *Ctx) error {
|
||||
}
|
||||
attrMap["error"] = rc.Err
|
||||
// 跳过log_handler等相关堆栈
|
||||
attrMap["stacktrace"] = runtimex.StatckStr(5, nFrames)
|
||||
attrMap["stacktrace"] = runtimex.StackStr(5, nFrames)
|
||||
}
|
||||
} else {
|
||||
// 处理文本格式日志信息
|
||||
@@ -134,6 +134,6 @@ func getErrMsg(rc *Ctx, err any) string {
|
||||
errMsg = fmt.Sprintf("\n<-e errMsg: %s", t)
|
||||
}
|
||||
// 加上堆栈信息
|
||||
errMsg += fmt.Sprintf("\n<-stacktrace: %s", runtimex.StatckStr(5, nFrames))
|
||||
errMsg += fmt.Sprintf("\n<-stacktrace: %s", runtimex.StackStr(5, nFrames))
|
||||
return (msg + errMsg)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@@ -13,9 +12,9 @@ import (
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mayfly-go/pkg/cache"
|
||||
"mayfly-go/pkg/logx"
|
||||
"mayfly-go/pkg/model"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
@@ -247,6 +246,7 @@ func AesDecrypt(data []byte, key []byte) ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//获取块的大小
|
||||
blockSize := block.BlockSize()
|
||||
//使用cbc
|
||||
@@ -281,65 +281,9 @@ func AesDecryptBase64(data string, key []byte) ([]byte, error) {
|
||||
return AesDecrypt(dataByte, key)
|
||||
}
|
||||
|
||||
// DES加密函数
|
||||
func DesEncrypt(data, key []byte) (string, error) {
|
||||
block, err := des.NewTripleDESCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 对数据进行填充
|
||||
data = pkcs7Padding(data, des.BlockSize)
|
||||
|
||||
// 创建一个初始化向量
|
||||
iv := make([]byte, des.BlockSize)
|
||||
if _, err := rand.Read(iv); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// 创建加密器
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
|
||||
// 加密
|
||||
encrypted := make([]byte, len(data))
|
||||
mode.CryptBlocks(encrypted, data)
|
||||
|
||||
// 将IV和加密数据组合
|
||||
result := append(iv, encrypted...)
|
||||
|
||||
// 使用Base64编码
|
||||
return base64.StdEncoding.EncodeToString(result), nil
|
||||
}
|
||||
|
||||
func DesDecryptByToken(data string, token string) (string, error) {
|
||||
key := []byte(token[:24])
|
||||
return DesDecrypt(data, key)
|
||||
}
|
||||
|
||||
func DesDecrypt(data string, key []byte) (string, error) {
|
||||
// Base64解码
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
block, err := des.NewTripleDESCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 确保密文长度正确
|
||||
if len(ciphertext) < des.BlockSize {
|
||||
return "", fmt.Errorf("ciphertext too short")
|
||||
}
|
||||
|
||||
// 提取IV
|
||||
iv := ciphertext[:des.BlockSize]
|
||||
ciphertext = ciphertext[des.BlockSize:]
|
||||
// 创建解密器
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
// 解密仍然用已存在的切片接收结果,无需重新创建切片
|
||||
mode.CryptBlocks(ciphertext, ciphertext)
|
||||
// 去除填充
|
||||
res, err := pkcs7UnPadding(ciphertext)
|
||||
func AesDecryptByLa(data string, la *model.LoginAccount) (string, error) {
|
||||
key := []byte(la.GetAesKey())
|
||||
res, err := AesDecryptBase64(data, key)
|
||||
return string(res), err
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,3 @@ func TestAesEncrypt(t *testing.T) {
|
||||
|
||||
t.Log(string(decrypt))
|
||||
}
|
||||
|
||||
func TestDes(t *testing.T) {
|
||||
key := []byte("eyJhbGciOiJIUzI1NiIsInR5")
|
||||
data := []byte("SELECT * FROM \"instruct\" OFFSET 0 LIMIT 25;")
|
||||
encrypt, err := DesEncrypt(data, key)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Log("encrypt", encrypt)
|
||||
decrypt, err := DesDecrypt(encrypt, key)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
t.Log("decrypt", decrypt)
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 获取指定堆栈描述信息
|
||||
// StackStr 获取指定堆栈描述信息
|
||||
//
|
||||
// @param skip: 跳过堆栈个数
|
||||
// @param nFrames: 需要描述的堆栈个数
|
||||
func StatckStr(skip, nFrames int) string {
|
||||
func StackStr(skip, nFrames int) string {
|
||||
pcs := make([]uintptr, nFrames+1)
|
||||
n := runtime.Callers(skip+1, pcs)
|
||||
if n == 0 {
|
||||
|
||||
@@ -2,7 +2,10 @@ package stringx
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const Nums = "0123456789"
|
||||
@@ -14,6 +17,11 @@ func Rand(l int) string {
|
||||
return RandByChars(l, Nums+LowerChars+UpperChars)
|
||||
}
|
||||
|
||||
// RandUUID
|
||||
func RandUUID() string {
|
||||
return strings.Replace(uuid.New().String(), "-", "", -1)
|
||||
}
|
||||
|
||||
// 根据传入的chars,随机生成指定位数的字符串
|
||||
func RandByChars(l int, chars string) string {
|
||||
strList := []byte(chars)
|
||||
|
||||
Reference in New Issue
Block a user