- 添加代码生成器完整使用说明文档,包含配置规则和自定义规则 - 新增 Common 工具类使用说明,介绍 Map/Slice/Obj 类型及转换函数 - 更新 QUICKSTART 文档中的配置项说明和数据库配置示例 - 完善请求参数获取方法,添加新版链式调用推荐用法 - 更新响应数据处理说明,包含错误码含义和自定义响应方法 - 优化中间件和 Session 操作的代码示例 - 修正路由路径参数获取的安全检查逻辑 - 更新 README 添加新文档链接索引
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)
|