Files
x_admin/server/core/null_int.go
2025-12-05 12:16:06 +08:00

156 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package core
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"strconv"
"x_admin/util/convert_util"
)
// 支持前端传递nullintstring类型和不传值
// 前端传1“1”都可以都转换为int64类型: NullInt{Int: 1, Exist: true}
// 前端null值: NullInt{Int: nil, Exist: true}
// 前端没传值: NullInt{Int: nil, Exist: false}
type NullInt struct {
Val *int64 // 整数或者null
Exist bool // 是否有值
}
func DecodeInt(value any) (any, error) {
switch v := value.(type) {
case nil:
return NullInt{Val: nil, Exist: false}, nil
case NullInt:
return v, nil
default:
result, err := convert_util.ToInt64(value)
if err != nil {
return NullInt{Val: nil, Exist: false}, err
}
return NullInt{Val: &result, Exist: true}, nil
}
}
// gorm实现Scanner
func (i *NullInt) Scan(value interface{}) error {
// 判断int64、string类型
switch v := value.(type) {
case nil:
i.Exist = true
return nil
case int64:
i.Val, i.Exist = &v, true
return nil
case string:
num, err := strconv.ParseInt(v, 10, 64)
if err == nil {
i.Val = &num
i.Exist = true
} else {
i.Exist = false
}
return err
default:
return fmt.Errorf("不能将类型 %T 转换为 int64", v)
}
}
// gorm实现 Valuer
func (i NullInt) Value() (driver.Value, error) {
if !i.Exist {
return nil, nil
}
v := i.Val
if v == nil {
return nil, nil
}
return *v, nil
}
func (i NullInt) String() string {
if i.Exist {
return strconv.FormatInt(*i.Val, 10)
} else {
return ""
}
}
// 实现json序列化接口
func (i NullInt) MarshalJSON() ([]byte, error) {
if i.Exist {
return json.Marshal(i.Val)
} else {
return json.Marshal(nil)
}
}
func (i *NullInt) UnmarshalText(text []byte) error {
return i.Scan(string(text))
}
// 实现gin框架的参数绑定接口
func (i *NullInt) UnmarshalParam(param string) error {
return i.Scan(param)
}
// 实现json反序列化接口,支持 int64, stringnull类型对于float64类型判断转换前后是否相等防止精度丢失
func (i *NullInt) UnmarshalJSON(data []byte) error {
var x any
if err := json.Unmarshal(data, &x); err != nil {
return err
}
switch v := x.(type) {
case nil:
i.Exist = true
return nil
case int64:
i.Val = &v
i.Exist = true
return nil
case float64:
i64 := int64(v)
// 判断转换前后是否相等,防止精度丢失
if float64(i64) != v {
i.Exist = false
return errors.New("int64转换失败" + fmt.Sprintf("%f", v) + "精度丢失")
}
i.Val = &i64
i.Exist = true
return nil
case string:
if v == "" {
i.Val = nil
i.Exist = true
return nil
}
num, err := strconv.ParseInt(v, 10, 64)
if err == nil {
i.Val = &num
i.Exist = true
} else {
i.Exist = false
}
return err
default:
return fmt.Errorf("不能将类型 %T 转换为 int64, 值为 %v", v, v)
}
}
func (i *NullInt) SetValue(value int64) {
i.Val = &value
i.Exist = true
}
func (i *NullInt) SetNull() {
i.Val = nil
i.Exist = true
}
func (i *NullInt) IsExists() bool {
return i.Exist
}
func (i *NullInt) GetValue() *int64 {
return i.Val
}