package tools import ( "errors" "fmt" "gorm.io/gorm" "log" "math" "reflect" "runtime" "strconv" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "github.com/spf13/cast" "golang.org/x/crypto/bcrypt" ) func CompareHashAndPassword(e string, p string) (bool, error) { err := bcrypt.CompareHashAndPassword([]byte(e), []byte(p)) if err != nil { return false, err } return true, nil } // Assert 条件断言 // 当断言条件为 假 时触发 panic // 对于当前请求不会再执行接下来的代码,并且返回指定格式的错误信息和错误码 func Assert(condition bool, msg string, code ...int) { if !condition { statusCode := 200 if len(code) > 0 { statusCode = code[0] } panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg) } } // HasError 错误断言 // 当 error 不为 nil 时触发 panic // 对于当前请求不会再执行接下来的代码,并且返回指定格式的错误信息和错误码 // 若 msg 为空,则默认为 error 中的内容 func HasError(err error, msg string, code ...int) { if err != nil { statusCode := 200 if len(code) > 0 { statusCode = code[0] } if msg == "" { msg = err.Error() } _, file, line, _ := runtime.Caller(1) log.Printf("%s:%v error: %#v", file, line, err) panic("CustomError#" + strconv.Itoa(statusCode) + "#" + msg) } } // GenerateMsgIDFromContext 生成msgID func GenerateMsgIDFromContext(c *gin.Context) string { var msgID string data, ok := c.Get("msgID") if !ok { msgID = uuid.New().String() c.Set("msgID", msgID) return msgID } msgID = cast.ToString(data) return msgID } // GetOrm 获取orm连接 func GetOrm(c *gin.Context) (*gorm.DB, error) { msgID := GenerateMsgIDFromContext(c) idb, exist := c.Get("db") if !exist { return nil, errors.New(fmt.Sprintf("msgID[%s], db connect not exist", msgID)) } switch idb.(type) { case *gorm.DB: //新增操作 return idb.(*gorm.DB), nil default: return nil, errors.New(fmt.Sprintf("msgID[%s], db connect not exist", msgID)) } } // RoundFloat64 将float64类型四舍五入取整 func RoundFloat64(input float64) int { rounded := int(math.Round(input)) return rounded } // ConvertTimeToString 将time类型转换为string func ConvertTimeToString(t time.Time) string { if t.IsZero() { return "" // 零值或 nil 返回空字符串 } return t.Format("2006-01-02 15:04:05") } // ConvertTimeToStringByPoint 将time类型转换为string func ConvertTimeToStringByPoint(t *time.Time) string { if t == nil { return "" // 零值或 nil 返回空字符串 } if t.IsZero() { return "" // 零值或 nil 返回空字符串 } return t.Format("2006-01-02 15:04:05") } // RoundToTwoDecimalPlaces 将float64类型四舍五入保留2位小数 func RoundToTwoDecimalPlaces(num float64) float64 { return math.Round(num*100) / 100 } // Uint32SliceContains 检查 uint32 切片中是否包含特定的值 func Uint32SliceContains(slice []uint32, val uint32) bool { for _, item := range slice { if item == val { return true } } return false } // StringSliceContains 检查 string 切片中是否包含特定的值 func StringSliceContains(slice []string, val string) bool { for _, item := range slice { if item == val { return true } } return false } // RoundFloat 保留 float64 两位小数 func RoundFloat(f float64) float64 { return math.Round(f*100) / 100 } // RoundFloatFields 递归处理结构体中的 float64 字段,四舍五入保留两位小数 func RoundFloatFields(v interface{}) { val := reflect.ValueOf(v).Elem() for i := 0; i < val.NumField(); i++ { field := val.Field(i) switch field.Kind() { case reflect.Float64: // 对 float64 类型进行四舍五入 field.SetFloat(RoundFloat(field.Float())) case reflect.Struct: // 递归处理子结构体 RoundFloatFields(field.Addr().Interface()) case reflect.Slice: // 对于 slice 中的结构体,逐个处理 for j := 0; j < field.Len(); j++ { if field.Index(j).Kind() == reflect.Struct { RoundFloatFields(field.Index(j).Addr().Interface()) } } } } }