hotime/docs/QUICKSTART.md
hoteas 8dac2aff66 docs(guides): 完善框架文档并新增代码生成器说明
- 添加代码生成器完整使用说明文档,包含配置规则和自定义规则
- 新增 Common 工具类使用说明,介绍 Map/Slice/Obj 类型及转换函数
- 更新 QUICKSTART 文档中的配置项说明和数据库配置示例
- 完善请求参数获取方法,添加新版链式调用推荐用法
- 更新响应数据处理说明,包含错误码含义和自定义响应方法
- 优化中间件和 Session 操作的代码示例
- 修正路由路径参数获取的安全检查逻辑
- 更新 README 添加新文档链接索引
2026-01-22 22:13:05 +08:00

13 KiB
Raw Permalink Blame History

HoTime 快速上手指南

5 分钟入门 HoTime 框架。

安装

go get code.hoteas.com/golang/hotime

最小示例

package main

import (
    . "code.hoteas.com/golang/hotime"
    . "code.hoteas.com/golang/hotime/common"
)

func main() {
    appIns := Init("config/config.json")
    
    appIns.Run(Router{
        "app": {
            "test": {
                "hello": func(that *Context) {
                    that.Display(0, Map{"message": "Hello World"})
                },
            },
        },
    })
}

访问: http://localhost:8081/app/test/hello

配置文件

创建 config/config.json:

{
    "port": "8081",
    "mode": 2,
    "sessionName": "HOTIME",
    "tpt": "tpt",
    "defFile": ["index.html", "index.htm"],
    "db": {
        "mysql": {
            "host": "localhost",
            "port": "3306",
            "name": "your_database",
            "user": "root",
            "password": "your_password",
            "prefix": ""
        }
    },
    "cache": {
        "memory": {
            "db": true,
            "session": true,
            "timeout": 7200
        }
    }
}

配置项说明

配置项 默认值 说明
port 80 HTTP 服务端口0 为不启用
tlsPort - HTTPS 端口,需配合 tlsCert/tlsKey
tlsCert - HTTPS 证书路径
tlsKey - HTTPS 密钥路径
mode 0 0=生产, 1=测试, 2=开发(输出SQL)
tpt tpt 静态文件目录
sessionName HOTIME Session Cookie 名称
modeRouterStrict false 路由大小写敏感false=忽略大小写
crossDomain - 跨域设置,空=不开启auto=智能开启,或指定域名
logFile - 日志文件路径,如 logs/20060102.txt
logLevel 0 日志等级0=关闭1=打印
webConnectLogShow true 是否显示访问日志
defFile ["index.html"] 目录默认访问文件

数据库配置

{
    "db": {
        "mysql": {
            "host": "127.0.0.1",
            "port": "3306",
            "name": "database_name",
            "user": "root",
            "password": "password",
            "prefix": "app_",
            "slave": {
                "host": "127.0.0.1",
                "port": "3306",
                "name": "database_name",
                "user": "root",
                "password": "password"
            }
        },
        "sqlite": {
            "path": "config/data.db",
            "prefix": ""
        }
    }
}

MySQL 配置 slave 项即启用主从读写分离

缓存配置

{
    "cache": {
        "memory": {
            "db": true,
            "session": true,
            "timeout": 7200
        },
        "redis": {
            "host": "127.0.0.1",
            "port": 6379,
            "password": "",
            "db": true,
            "session": true,
            "timeout": 1296000
        },
        "db": {
            "db": true,
            "session": true,
            "timeout": 2592000
        }
    }
}

缓存优先级: Memory > Redis > DB,自动穿透与回填

错误码配置

{
    "error": {
        "1": "内部系统异常",
        "2": "访问权限异常",
        "3": "请求参数异常",
        "4": "数据处理异常",
        "5": "数据结果异常"
    }
}

自定义错误码建议从 10 开始

路由系统

HoTime 使用三层路由结构:模块/控制器/方法

appIns.Run(Router{
    "模块名": {
        "控制器名": {
            "方法名": func(that *Context) {
                // 处理逻辑
            },
        },
    },
})

路由路径

// 获取路由信息
module := that.RouterString[0]    // 模块
controller := that.RouterString[1] // 控制器
action := that.RouterString[2]     // 方法

// 完整请求路径
fullPath := that.HandlerStr // 如 /app/user/login

请求参数获取

新版推荐方法(支持链式调用)

// 获取 URL 查询参数 (?id=1)
id := that.ReqParam("id").ToInt()
name := that.ReqParam("name").ToStr()

// 获取表单参数 (POST form-data / x-www-form-urlencoded)
username := that.ReqForm("username").ToStr()
age := that.ReqForm("age").ToInt()

// 获取 JSON Body 参数 (POST application/json)
data := that.ReqJson("data").ToMap()
items := that.ReqJson("items").ToSlice()

// 统一获取(自动判断来源,优先级: JSON > Form > URL
userId := that.ReqData("user_id").ToInt()
status := that.ReqData("status").ToStr()

类型转换方法

obj := that.ReqData("key")

obj.ToStr()      // 转字符串
obj.ToInt()      // 转 int
obj.ToInt64()    // 转 int64
obj.ToFloat64()  // 转 float64
obj.ToBool()     // 转 bool
obj.ToMap()      // 转 Map
obj.ToSlice()    // 转 Slice
obj.Data         // 获取原始值interface{}

文件上传

// 单文件上传
file, header, err := that.ReqFile("avatar")
if err == nil {
    defer file.Close()
    // header.Filename - 文件名
    // header.Size - 文件大小
}

// 多文件上传(批量)
files, err := that.ReqFiles("images")
if err == nil {
    for _, fh := range files {
        file, _ := fh.Open()
        defer file.Close()
        // 处理每个文件
    }
}

传统方法(兼容)

// GET/POST 参数
name := that.Req.FormValue("name")

// URL 参数
id := that.Req.URL.Query().Get("id")

// 请求头
token := that.Req.Header.Get("Authorization")

响应数据

Display 方法

// 成功响应 (status=0)
that.Display(0, Map{"user": user, "token": token})
// 输出: {"status":0, "result":{"user":..., "token":...}}

// 错误响应 (status>0)
that.Display(1, "系统内部错误")
// 输出: {"status":1, "result":{"type":"内部系统异常", "msg":"系统内部错误"}, "error":{...}}

that.Display(2, "请先登录")
// 输出: {"status":2, "result":{"type":"访问权限异常", "msg":"请先登录"}, "error":{...}}

that.Display(3, "参数不能为空")
// 输出: {"status":3, "result":{"type":"请求参数异常", "msg":"参数不能为空"}, "error":{...}}

错误码含义

错误码 类型 使用场景
0 成功 请求成功
1 内部系统异常 环境配置、文件权限等基础运行环境错误
2 访问权限异常 未登录或登录异常
3 请求参数异常 参数不足、类型错误等
4 数据处理异常 数据库操作或第三方请求返回异常
5 数据结果异常 无法返回要求的格式

自定义响应

// 自定义 Header
that.Resp.Header().Set("Content-Type", "application/json")

// 直接写入
that.Resp.Write([]byte("raw data"))

// 自定义响应函数
that.RespFunc = func() {
    // 自定义响应逻辑
}

中间件

// 全局中间件(请求拦截)
appIns.SetConnectListener(func(that *Context) bool {
    // 放行登录接口
    if len(that.RouterString) >= 3 && that.RouterString[2] == "login" {
        return false
    }
    
    // 检查登录状态
    if that.Session("user_id").Data == nil {
        that.Display(2, "请先登录")
        return true  // 返回 true 终止请求
    }
    return false  // 返回 false 继续处理
})

Session 与缓存

// Session 操作
that.Session("user_id", 123)          // 设置
userId := that.Session("user_id")     // 获取 *Obj
that.Session("user_id", nil)          // 删除

// 链式获取
id := that.Session("user_id").ToInt64()
name := that.Session("username").ToStr()

// 通用缓存
that.Cache("key", "value")            // 设置
data := that.Cache("key")             // 获取
that.Cache("key", nil)                // 删除

三级缓存自动运作:Memory → Redis → Database

数据库操作(简要)

基础 CRUD

// 查询列表
users := that.Db.Select("user", "*", Map{"status": 1})

// 查询单条
user := that.Db.Get("user", "*", Map{"id": 1})

// 插入
id := that.Db.Insert("user", Map{"name": "test", "age": 18})

// 批量插入
affected := that.Db.Inserts("user", []Map{
    {"name": "user1", "age": 20},
    {"name": "user2", "age": 25},
})

// 更新
rows := that.Db.Update("user", Map{"name": "new"}, Map{"id": 1})

// 删除
rows := that.Db.Delete("user", Map{"id": 1})

链式查询

users := that.Db.Table("user").
    LeftJoin("order", "user.id=order.user_id").
    Where("status", 1).
    And("age[>]", 18).
    Order("id DESC").
    Page(1, 10).
    Select("*")

条件语法速查

语法 说明 示例
key 等于 "id": 1
key[>] 大于 "age[>]": 18
key[<] 小于 "age[<]": 60
key[>=] 大于等于 "age[>=]": 18
key[<=] 小于等于 "age[<=]": 60
key[!] 不等于 "status[!]": 0
key[~] LIKE "name[~]": "test"
key[<>] BETWEEN "age[<>]": Slice{18, 60}
key IN "id": Slice{1, 2, 3}

事务

success := that.Db.Action(func(tx db.HoTimeDB) bool {
    tx.Update("user", Map{"balance[#]": "balance - 100"}, Map{"id": 1})
    tx.Insert("order", Map{"user_id": 1, "amount": 100})
    return true  // 返回 true 提交false 回滚
})

更多数据库操作:参见 HoTimeDB 使用说明

日志记录

// 创建操作日志(自动插入 logs 表)
that.Log = Map{
    "type":   "login",
    "action": "用户登录",
    "data":   Map{"phone": phone},
}
// 框架会自动添加 time, admin_id/user_id, ip 等字段

扩展功能

功能 路径 说明
微信支付/公众号/小程序 dri/wechat/ 微信全套 SDK
阿里云服务 dri/aliyun/ 企业认证等
腾讯云服务 dri/tencent/ 企业认证等
文件上传 dri/upload/ 文件上传处理
文件下载 dri/download/ 文件下载处理
MongoDB dri/mongodb/ MongoDB 驱动
RSA 加解密 dri/rsa/ RSA 加解密工具

完整示例

package main

import (
    . "code.hoteas.com/golang/hotime"
    . "code.hoteas.com/golang/hotime/common"
)

func main() {
    appIns := Init("config/config.json")
    
    // 登录检查中间件
    appIns.SetConnectListener(func(that *Context) bool {
        // 放行登录接口
        if len(that.RouterString) >= 3 && that.RouterString[2] == "login" {
            return false
        }
        if that.Session("user_id").Data == nil {
            that.Display(2, "请先登录")
            return true
        }
        return false
    })

    appIns.Run(Router{
        "api": {
            "user": {
                "login": func(that *Context) {
                    phone := that.ReqData("phone").ToStr()
                    password := that.ReqData("password").ToStr()
                    
                    if phone == "" || password == "" {
                        that.Display(3, "手机号和密码不能为空")
                        return
                    }
                    
                    user := that.Db.Get("user", "*", Map{
                        "phone": phone,
                        "password": Md5(password),
                    })
                    
                    if user == nil {
                        that.Display(3, "账号或密码错误")
                        return
                    }
                    
                    that.Session("user_id", user.GetInt64("id"))
                    that.Display(0, Map{"user": user})
                },
                
                "info": func(that *Context) {
                    userId := that.Session("user_id").ToInt64()
                    user := that.Db.Get("user", "*", Map{"id": userId})
                    that.Display(0, Map{"user": user})
                },
                
                "list": func(that *Context) {
                    page := that.ReqData("page").ToInt()
                    if page == 0 {
                        page = 1
                    }
                    
                    users := that.Db.Table("user").
                        Where("status", 1).
                        Order("id DESC").
                        Page(page, 10).
                        Select("id,name,phone,created_at")
                    
                    total := that.Db.Count("user", Map{"status": 1})
                    
                    that.Display(0, Map{
                        "list":  users,
                        "total": total,
                        "page":  page,
                    })
                },
                
                "logout": func(that *Context) {
                    that.Session("user_id", nil)
                    that.Display(0, "退出成功")
                },
            },
        },
    })
}

下一步