485 lines
9.7 KiB
Markdown
485 lines
9.7 KiB
Markdown
|
|
# HoTime Common 工具类使用说明
|
|||
|
|
|
|||
|
|
`common` 包提供了 HoTime 框架的核心数据类型和工具函数,包括 `Map`、`Slice`、`Obj` 类型及丰富的类型转换函数。
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
|
|||
|
|
- [核心数据类型](#核心数据类型)
|
|||
|
|
- [Map 类型](#map-类型)
|
|||
|
|
- [Slice 类型](#slice-类型)
|
|||
|
|
- [Obj 类型](#obj-类型)
|
|||
|
|
- [类型转换函数](#类型转换函数)
|
|||
|
|
- [工具函数](#工具函数)
|
|||
|
|
- [错误处理](#错误处理)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 核心数据类型
|
|||
|
|
|
|||
|
|
### Map 类型
|
|||
|
|
|
|||
|
|
`Map` 是 `map[string]interface{}` 的别名,提供了丰富的链式调用方法。
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
import . "code.hoteas.com/golang/hotime/common"
|
|||
|
|
|
|||
|
|
// 创建 Map
|
|||
|
|
data := Map{
|
|||
|
|
"name": "张三",
|
|||
|
|
"age": 25,
|
|||
|
|
"score": 98.5,
|
|||
|
|
"active": true,
|
|||
|
|
"tags": Slice{"Go", "Web"},
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 获取值方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 获取字符串
|
|||
|
|
name := data.GetString("name") // "张三"
|
|||
|
|
|
|||
|
|
// 获取整数
|
|||
|
|
age := data.GetInt("age") // 25
|
|||
|
|
age64 := data.GetInt64("age") // int64(25)
|
|||
|
|
|
|||
|
|
// 获取浮点数
|
|||
|
|
score := data.GetFloat64("score") // 98.5
|
|||
|
|
|
|||
|
|
// 获取布尔值
|
|||
|
|
active := data.GetBool("active") // true
|
|||
|
|
|
|||
|
|
// 获取嵌套 Map
|
|||
|
|
info := data.GetMap("info") // 返回 Map 类型
|
|||
|
|
|
|||
|
|
// 获取 Slice
|
|||
|
|
tags := data.GetSlice("tags") // 返回 Slice 类型
|
|||
|
|
|
|||
|
|
// 获取时间
|
|||
|
|
createTime := data.GetTime("create_time") // 返回 *time.Time
|
|||
|
|
|
|||
|
|
// 获取原始值
|
|||
|
|
raw := data.Get("name") // interface{}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 向上取整方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 向上取整获取整数
|
|||
|
|
ceilInt := data.GetCeilInt("score") // 99
|
|||
|
|
ceilInt64 := data.GetCeilInt64("score") // int64(99)
|
|||
|
|
ceilFloat := data.GetCeilFloat64("score") // 99.0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 操作方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 添加/修改值
|
|||
|
|
data.Put("email", "test@example.com")
|
|||
|
|
|
|||
|
|
// 删除值
|
|||
|
|
data.Delete("email")
|
|||
|
|
|
|||
|
|
// 转换为 JSON 字符串
|
|||
|
|
jsonStr := data.ToJsonString()
|
|||
|
|
|
|||
|
|
// 从 JSON 字符串解析
|
|||
|
|
data.JsonToMap(`{"key": "value"}`)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 有序遍历
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 按 key 字母顺序遍历
|
|||
|
|
data.RangeSort(func(k string, v interface{}) bool {
|
|||
|
|
fmt.Printf("%s: %v\n", k, v)
|
|||
|
|
return false // 返回 true 则终止遍历
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 转换为结构体
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
type User struct {
|
|||
|
|
Name string
|
|||
|
|
Age int64
|
|||
|
|
Score float64
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var user User
|
|||
|
|
data.ToStruct(&user) // 传入指针,字段名首字母大写匹配
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Slice 类型
|
|||
|
|
|
|||
|
|
`Slice` 是 `[]interface{}` 的别名,提供类似 Map 的链式调用方法。
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 创建 Slice
|
|||
|
|
list := Slice{
|
|||
|
|
Map{"id": 1, "name": "Alice"},
|
|||
|
|
Map{"id": 2, "name": "Bob"},
|
|||
|
|
"text",
|
|||
|
|
123,
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 获取值方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 按索引获取值(类型转换)
|
|||
|
|
str := list.GetString(2) // "text"
|
|||
|
|
num := list.GetInt(3) // 123
|
|||
|
|
num64 := list.GetInt64(3) // int64(123)
|
|||
|
|
f := list.GetFloat64(3) // 123.0
|
|||
|
|
b := list.GetBool(3) // true (非0为true)
|
|||
|
|
|
|||
|
|
// 获取嵌套类型
|
|||
|
|
item := list.GetMap(0) // Map{"id": 1, "name": "Alice"}
|
|||
|
|
subList := list.GetSlice(0) // 尝试转换为 Slice
|
|||
|
|
|
|||
|
|
// 获取原始值
|
|||
|
|
raw := list.Get(0) // interface{}
|
|||
|
|
|
|||
|
|
// 获取时间
|
|||
|
|
t := list.GetTime(0) // *time.Time
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 向上取整方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
ceilInt := list.GetCeilInt(3)
|
|||
|
|
ceilInt64 := list.GetCeilInt64(3)
|
|||
|
|
ceilFloat := list.GetCeilFloat64(3)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 操作方法
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 修改指定位置的值
|
|||
|
|
list.Put(0, "new value")
|
|||
|
|
|
|||
|
|
// 转换为 JSON 字符串
|
|||
|
|
jsonStr := list.ToJsonString()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Obj 类型
|
|||
|
|
|
|||
|
|
`Obj` 是一个通用的对象包装器,用于链式类型转换,常用于 `Context` 方法的返回值。
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
type Obj struct {
|
|||
|
|
Data interface{} // 原始数据
|
|||
|
|
Error // 错误信息
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 使用示例
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
obj := &Obj{Data: "123"}
|
|||
|
|
|
|||
|
|
// 链式类型转换
|
|||
|
|
i := obj.ToInt() // 123
|
|||
|
|
i64 := obj.ToInt64() // int64(123)
|
|||
|
|
f := obj.ToFloat64() // 123.0
|
|||
|
|
s := obj.ToStr() // "123"
|
|||
|
|
b := obj.ToBool() // true
|
|||
|
|
|
|||
|
|
// 复杂类型转换
|
|||
|
|
m := obj.ToMap() // 尝试转换为 Map
|
|||
|
|
sl := obj.ToSlice() // 尝试转换为 Slice
|
|||
|
|
arr := obj.ToMapArray() // 转换为 []Map
|
|||
|
|
|
|||
|
|
// 获取原始值
|
|||
|
|
raw := obj.ToObj() // interface{}
|
|||
|
|
|
|||
|
|
// 获取时间
|
|||
|
|
t := obj.ToTime() // *time.Time
|
|||
|
|
|
|||
|
|
// 向上取整
|
|||
|
|
ceil := obj.ToCeilInt()
|
|||
|
|
ceil64 := obj.ToCeilInt64()
|
|||
|
|
ceilF := obj.ToCeilFloat64()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 在 Context 中的应用
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func handler(that *Context) {
|
|||
|
|
// ReqData 返回 *Obj,支持链式调用
|
|||
|
|
userId := that.ReqData("user_id").ToInt()
|
|||
|
|
name := that.ReqData("name").ToStr()
|
|||
|
|
|
|||
|
|
// Session 也返回 *Obj
|
|||
|
|
adminId := that.Session("admin_id").ToInt64()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 类型转换函数
|
|||
|
|
|
|||
|
|
`common` 包提供了一系列全局类型转换函数。
|
|||
|
|
|
|||
|
|
### 基础转换
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 转字符串
|
|||
|
|
str := ObjToStr(123) // "123"
|
|||
|
|
str := ObjToStr(3.14) // "3.14"
|
|||
|
|
str := ObjToStr(Map{"a": 1}) // JSON 格式字符串
|
|||
|
|
|
|||
|
|
// 转整数
|
|||
|
|
i := ObjToInt("123") // 123
|
|||
|
|
i64 := ObjToInt64("123") // int64(123)
|
|||
|
|
|
|||
|
|
// 转浮点数
|
|||
|
|
f := ObjToFloat64("3.14") // 3.14
|
|||
|
|
|
|||
|
|
// 转布尔
|
|||
|
|
b := ObjToBool(1) // true
|
|||
|
|
b := ObjToBool(0) // false
|
|||
|
|
|
|||
|
|
// 转 Map
|
|||
|
|
m := ObjToMap(`{"a": 1}`) // Map{"a": 1}
|
|||
|
|
m := ObjToMap(someStruct) // 结构体转 Map
|
|||
|
|
|
|||
|
|
// 转 Slice
|
|||
|
|
s := ObjToSlice(`[1, 2, 3]`) // Slice{1, 2, 3}
|
|||
|
|
|
|||
|
|
// 转 []Map
|
|||
|
|
arr := ObjToMapArray(slice) // []Map
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 向上取整转换
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 向上取整后转整数
|
|||
|
|
ceil := ObjToCeilInt(3.2) // 4
|
|||
|
|
ceil64 := ObjToCeilInt64(3.2) // int64(4)
|
|||
|
|
ceilF := ObjToCeilFloat64(3.2) // 4.0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 时间转换
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 自动识别多种格式
|
|||
|
|
t := ObjToTime("2024-01-15 10:30:00") // *time.Time
|
|||
|
|
t := ObjToTime("2024-01-15") // *time.Time
|
|||
|
|
t := ObjToTime(1705298400) // Unix 秒
|
|||
|
|
t := ObjToTime(1705298400000) // Unix 毫秒
|
|||
|
|
t := ObjToTime(1705298400000000) // Unix 微秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 字符串转换
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 字符串转 Map
|
|||
|
|
m := StrToMap(`{"key": "value"}`)
|
|||
|
|
|
|||
|
|
// 字符串转 Slice
|
|||
|
|
s := StrToSlice(`[1, 2, 3]`)
|
|||
|
|
|
|||
|
|
// 字符串转 int
|
|||
|
|
i, err := StrToInt("123")
|
|||
|
|
|
|||
|
|
// 字符串数组格式转换
|
|||
|
|
jsonArr := StrArrayToJsonStr("a1,a2,a3") // "[a1,a2,a3]"
|
|||
|
|
strArr := JsonStrToStrArray("[a1,a2,a3]") // ",a1,a2,a3,"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 错误处理
|
|||
|
|
|
|||
|
|
所有转换函数支持可选的错误参数:
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
var e Error
|
|||
|
|
i := ObjToInt("abc", &e)
|
|||
|
|
if e.GetError() != nil {
|
|||
|
|
// 处理转换错误
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 工具函数
|
|||
|
|
|
|||
|
|
### 字符串处理
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 字符串截取(支持中文)
|
|||
|
|
str := Substr("Hello世界", 0, 7) // "Hello世"
|
|||
|
|
str := Substr("Hello", -2, 2) // "lo" (负数从末尾计算)
|
|||
|
|
|
|||
|
|
// 首字母大写
|
|||
|
|
upper := StrFirstToUpper("hello") // "Hello"
|
|||
|
|
|
|||
|
|
// 查找最后出现位置
|
|||
|
|
idx := IndexLastStr("a.b.c", ".") // 3
|
|||
|
|
|
|||
|
|
// 字符串相似度(Levenshtein 距离)
|
|||
|
|
dist := StrLd("hello", "hallo", true) // 1 (忽略大小写)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 时间处理
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 时间转字符串
|
|||
|
|
str := Time2Str(time.Now()) // "2024-01-15 10:30:00"
|
|||
|
|
str := Time2Str(time.Now(), 1) // "2024-01"
|
|||
|
|
str := Time2Str(time.Now(), 2) // "2024-01-15"
|
|||
|
|
str := Time2Str(time.Now(), 3) // "2024-01-15 10"
|
|||
|
|
str := Time2Str(time.Now(), 4) // "2024-01-15 10:30"
|
|||
|
|
str := Time2Str(time.Now(), 5) // "2024-01-15 10:30:00"
|
|||
|
|
|
|||
|
|
// 特殊格式
|
|||
|
|
str := Time2Str(time.Now(), 12) // "01-15"
|
|||
|
|
str := Time2Str(time.Now(), 14) // "01-15 10:30"
|
|||
|
|
str := Time2Str(time.Now(), 34) // "10:30"
|
|||
|
|
str := Time2Str(time.Now(), 35) // "10:30:00"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 加密与随机
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// MD5 加密
|
|||
|
|
hash := Md5("password") // 32位小写MD5
|
|||
|
|
|
|||
|
|
// 随机数
|
|||
|
|
r := Rand(3) // 3位随机数 (0-999)
|
|||
|
|
r := RandX(10, 100) // 10-100之间的随机数
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 数学计算
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 四舍五入保留小数
|
|||
|
|
f := Round(3.14159, 2) // 3.14
|
|||
|
|
f := Round(3.145, 2) // 3.15
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 深拷贝
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 深拷贝 Map/Slice(递归复制)
|
|||
|
|
original := Map{"a": Map{"b": 1}}
|
|||
|
|
copied := DeepCopyMap(original).(Map)
|
|||
|
|
|
|||
|
|
// 修改副本不影响原始数据
|
|||
|
|
copied.GetMap("a")["b"] = 2
|
|||
|
|
// original["a"]["b"] 仍然是 1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 错误处理
|
|||
|
|
|
|||
|
|
### Error 类型
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
type Error struct {
|
|||
|
|
Logger *logrus.Logger // 可选的日志记录器
|
|||
|
|
error // 内嵌错误
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 使用示例
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
var e Error
|
|||
|
|
|
|||
|
|
// 设置错误
|
|||
|
|
e.SetError(errors.New("something wrong"))
|
|||
|
|
|
|||
|
|
// 获取错误
|
|||
|
|
if err := e.GetError(); err != nil {
|
|||
|
|
fmt.Println(err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 配合日志自动记录
|
|||
|
|
e.Logger = logrusLogger
|
|||
|
|
e.SetError(errors.New("will be logged"))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 在类型转换中使用
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
var e Error
|
|||
|
|
data := Map{"count": "abc"}
|
|||
|
|
|
|||
|
|
count := data.GetInt("count", &e)
|
|||
|
|
if e.GetError() != nil {
|
|||
|
|
// 转换失败,count = 0
|
|||
|
|
fmt.Println("转换失败:", e.GetError())
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 最佳实践
|
|||
|
|
|
|||
|
|
### 1. 链式调用处理请求数据
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func handler(that *Context) {
|
|||
|
|
// 推荐:使用 Obj 链式调用
|
|||
|
|
userId := that.ReqData("user_id").ToInt()
|
|||
|
|
page := that.ReqData("page").ToInt()
|
|||
|
|
if page < 1 {
|
|||
|
|
page = 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理 Map 数据
|
|||
|
|
user := that.Db.Get("user", "*", Map{"id": userId})
|
|||
|
|
if user != nil {
|
|||
|
|
name := user.GetString("name")
|
|||
|
|
age := user.GetInt("age")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 安全的类型转换
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 带错误检查的转换
|
|||
|
|
var e Error
|
|||
|
|
data := someMap.GetInt("key", &e)
|
|||
|
|
if e.GetError() != nil {
|
|||
|
|
// 使用默认值
|
|||
|
|
data = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 简单场景直接转换(失败返回零值)
|
|||
|
|
data := someMap.GetInt("key") // 失败返回 0
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 处理数据库查询结果
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 查询返回 Map
|
|||
|
|
user := that.Db.Get("user", "*", Map{"id": 1})
|
|||
|
|
if user != nil {
|
|||
|
|
name := user.GetString("name")
|
|||
|
|
createTime := user.GetTime("create_time")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询返回 []Map
|
|||
|
|
users := that.Db.Select("user", "*", Map{"status": 1})
|
|||
|
|
for _, u := range users {
|
|||
|
|
fmt.Printf("ID: %d, Name: %s\n", u.GetInt("id"), u.GetString("name"))
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 相关文档
|
|||
|
|
|
|||
|
|
- [快速上手指南](QUICKSTART.md)
|
|||
|
|
- [HoTimeDB 使用说明](HoTimeDB_使用说明.md)
|
|||
|
|
- [代码生成器使用说明](CodeGen_使用说明.md)
|