# gogo
**Repository Path**: konyshe/gogo
## Basic Information
- **Project Name**: gogo
- **Description**: 轻量 web 开发框架,特点是一行代码搞定 RESTFul,无需一堆的 controllers 和 models 文件,快速使用,性能优秀。v4部分理论性能优于spring、kafka、nginx
- **Primary Language**: Go
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 108
- **Forks**: 28
- **Created**: 2018-06-18
- **Last Updated**: 2025-10-22
## Categories & Tags
**Categories**: webframework
**Tags**: None
## README

[](https://golang.org/)
[](https://gitee.com/konyshe/gogo)
[](https://gitee.com/konyshe/gogo)
[]()
**Go 语言轻量级 Web 开发框架,一行代码搞定 RESTful API**
---
## ✨ 主要功能
🚀 一行代码RESTful
无需繁琐配置,一行代码搞定CRUD操作
|
⚡ Epoll异步架构
可选v3版本,基于epoll实现,针对低性能设备
|
📡 WebSocket支持
内置完整的WebSocket连接管理和消息广播
|
📦 零依赖ORM
内置轻量级SQL操作,不依赖第三方ORM
|
🔐 认证系统
支持HTTP Basic认证和自定义认证扩展
|
🔒 HTTPS支持
内置HTTPS服务,支持TLS加密传输
|
🌐 主机名路由
支持基于主机名的路由分离,实现多域名服务
|
🔀 URL转发
内置请求转发功能,支持反向代理https
|
## 🏗️ 系统架构
```mermaid
graph TB
subgraph "应用层"
A[用户应用]
B[示例程序]
end
subgraph "框架API层"
C[路由注册 API]
D[WebSocket API]
E[认证 API]
F[数据库 API]
end
subgraph "核心处理层"
G[HTTP路由器]
H[WebSocket服务]
I[认证系统]
J[上下文管理]
end
subgraph "网络服务层"
K[HTTP服务 v1/v2]
L[HTTP服务 v3]
M[WebSocket服务器]
N[HTTPS服务]
end
subgraph "数据存储层"
O[(MySQL)]
P[(PostgreSQL)]
Q[(SQLite)]
end
A --> C
B --> C
C --> G
D --> H
E --> I
F --> J
G --> K
G --> L
H --> M
I --> N
J --> O
J --> P
J --> Q
style L fill:#ff6b6b
style M fill:#4ecdc4
style N fill:#45b7d1
```
### 🔄 版本演进
| 版本 | 状态 | 核心特性 |
|------|------|----------|
| **v1** | ✅ 已发布 | 基础HTTP服务、RESTful路由 |
| **v2** | ✅ 已发布 | WebSocket支持、连接管理 |
| **v3** | 🚧 测试中 | 基于epoll开发、协程可控,异步实现 |
| **v4** | 📋 开发中 | 基于网卡驱动开发、性能优化 |
## 🚀 快速开始
### 📦 安装
```bash
# 从 Gitee 安装(推荐)
go get gitee.com/konyshe/gogo
# 或从 GitCode 安装
go get gitcode.com/konyshe/gogo
```
## 快速使用
备注:由于嵌入了C代码,若遇到提示gcc无法编译的问题,可删掉UtilsBuild_linux.go文件后再尝试
```go
package main
import (
"log"
"net/http"
"strconv"
"gitcode.com/konyshe/gogo" //二选一即可
"gitee.com/konyshe/gogo" //二选一即可
)
func main() {
// 初始化数据库连接
if err := gogo.SQLInit("mysql", "数据库用户名:数据库密码@tcp(数据库地址:数据库端口)/表名?charset=utf8", 10, 1); err != nil {
log.Fatalf("SQLInit error: %v", err)
}
// 增
gogo.POST("/restful/:tablename", func(ctx *gogo.HTTPContext) {
affect, err := gogo.SQLInsert(
ctx.GetPathParam(":tablename"),
ctx.GetPostBody())
if err != nil {
log.Fatalf("SQLInit error: %v", err)
ctx.WriteString(err.Error())
} else {
ctx.WriteString(strconv.FormatInt(affect, 10))
}
})
// 删
gogo.DELETE("/restful/:tablename/:id", func(ctx *gogo.HTTPContext) {
affect, err := gogo.SQLDelete(
ctx.GetPathParam(":tablename"),
"id="+ctx.GetPathParam(":id"))
if err != nil {
log.Fatalf("SQLInit error: %v", err)
ctx.WriteString(err.Error())
} else {
ctx.WriteString(strconv.FormatInt(affect, 10))
}
})
// 改
gogo.PUT("/restful/:tablename/:id", func(ctx *gogo.HTTPContext) {
affect, err := gogo.SQLUpdate(
ctx.GetPathParam(":tablename"),
"id="+ctx.GetPathParam(":id"),
ctx.GetPostBody())
if err != nil {
log.Fatalf("SQLInit error: %v", err)
ctx.WriteString(err.Error())
} else {
ctx.WriteString(strconv.FormatInt(affect, 10))
}
})
// 查
gogo.GET("/restful/:tablename/:id", func(ctx *gogo.HTTPContext) {
queryData, err := gogo.SQLQueryByMap(
"",
ctx.GetString("feilds"),
ctx.GetPathParam(":tablename"),
"id="+ctx.GetPathParam(":id"),
"", 0, 1)
if err != nil {
log.Fatalf("SQLInit error: %v", err)
ctx.WriteString(err.Error())
} else {
ctx.WriteJSON(queryData)
}
})
// 查
gogo.GET("/restful/:tablename", func(ctx *gogo.HTTPContext) {
queryData, err := gogo.SQLQueryByMap(
ctx.GetString("columnname"),
ctx.GetString("feilds"),
ctx.GetPathParam(":tablename"),
ctx.GetString("where"),
ctx.GetString("order"),
ctx.GetInt("offset", 0),
ctx.GetInt("count", 10))
if err != nil {
log.Fatalf("SQLInit error: %v", err)
ctx.WriteString(err.Error())
} else {
ctx.WriteJSON(queryData)
}
})
// 404页面
gogo.STATUS(http.StatusNotFound, func(ctx *gogo.HTTPContext) {
ctx.WriteHeaderStatus(http.StatusNotFound)
ctx.WriteString("Page Not Found !")
})
// 启动HTTP服务
gogo.StartHTTP(3009)
}
```
## 数据库表结构
```mysql
mysql> desc dede_flink;
+----------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------------------+------+-----+---------+----------------+
| id | smallint(5) unsigned | NO | PRI | NULL | auto_increment |
| sortrank | smallint(6) | NO | | 0 | |
| url | char(60) | NO | | | |
| webname | char(30) | NO | | | |
| msg | char(200) | NO | | | |
| email | char(50) | NO | | | |
| logo | char(60) | NO | | | |
| dtime | int(10) unsigned | NO | | 0 | |
| typeid | smallint(5) unsigned | NO | | 0 | |
| ischeck | smallint(6) | NO | | 1 | |
+----------+----------------------+------+-----+---------+----------------+
10 rows in set
```
## 浏览器访问测试
- 增
```
POST http://localhost:3009/restful/dede_flink
```
以下是 application/json 内容,可以批量添加多条数据
```
[
{
"id": 20,
"ischeck": 1,
"webname": "hxyw",
"url":"http://www.hxyw.org"
},
{
"id": 21,
"ischeck": 1,
"webname": "bejson",
"url":"http://www.bejson.com"
}
]
```
- 改
```
PUT http://localhost:3009/restful/dede_flink/21
```
以下是 application/json 内容,这里只将 id=21 的数据,webname 字段修改为"hello"
```
{
"webname": "hello"
}
```
- 查
```
GET http://localhost:3009/restful/dede_flink/21
GET http://localhost:3009/restful/dede_flink?order=-id
GET http://localhost:3009/restful/dede_flink?offset=10&&count=100&&columnname=webname
```
- 删
```
DELETE http://localhost:3009/restful/dede_flink/1
```
- 404
```
GET http://localhost:3009/weqwe
```
## 📚 其他示例代码
### 📂 示例目录
- [forward](#forward) - URL转发功能示例,演示如何将请求转发到其他服务器
- [get_pre](#get_pre) - 权限控制示例,演示HTTP Basic Auth和自定义认证
- [http](#http) - 基础HTTP服务示例,演示RESTful API的完整CRUD操作
- [http_basicauth](#http_basicauth) - HTTP Basic认证示例,演示如何添加基础认证保护
- [http_v3](#http_v3) - v3高性能HTTP服务器示例,基于epoll实现
- [https](#https) - HTTPS服务示例,演示SSL/TLS加密传输
- [https_v3](#https_v3) - v3高性能HTTPS服务器示例,支持TLS的epoll实现
- [test_https](#test_https) - Test_https 功能示例
- [host_routing](#host_routing) - 主机名路由示例,演示多域名服务部署
## ⚡ V3版本(测试中)
- [x] 基于epoll重写了http服务,目标是极少的协程数量,异步方式处理并发,无锁,针对低性能设备,树莓派、入门版云主机等
- [x] gogo.StartHTTP使用Google的http(目前最稳定),gogo.StartHTTPV3使用v3方案,使用方法一致
```go
// 使用 epoll 实现的高性能服务器
gogo.StartHTTPV3(3009, 4) // 4个工作线程
```
注:Google的http框架针对每个TCP连接,都会创建一个goroutine,如果后端业务来不及,就会积压goroutine,导致REST和后端宕机。GoGo v3的目标是可控的goroutine数量前提,利用异步实现并发,REST只需较低性能,并且不会造成后端宕机
## v4(开发中)
- [x] 基于网卡驱动重写了epoll,目标是内核态性能优化,将性能提高到极致
注:按照内核设计,数据包到网卡寄存器后,由DMA拷贝到指定地址,再由驱动拷贝到skbuf等内核处理,内核处理后拷贝进队列等协议栈处理,协议栈处理后拷贝进队列,然后发送中断等用户态处理,最后用户态通过recv函数拷贝到指定地址。除第一次DMA拷贝,之后有4次CPU拷贝,特别是最后一次内核态到用户态的拷贝,加上中断,性能消耗很大。v4只有一次DMA拷贝。同时搭配用户态tcp/ip协议栈,零拷贝,bbr流量控制
## 📖 API 参考
### 🛣️ 路由注册
| 方法 | 语法 | 描述 |
|------|------|------|
| **GET** | `gogo.GET(path, handler)` | 注册GET路由 |
| **POST** | `gogo.POST(path, handler)` | 注册POST路由 |
| **PUT** | `gogo.PUT(path, handler)` | 注册PUT路由 |
| **DELETE** | `gogo.DELETE(path, handler)` | 注册DELETE路由 |
| **ANY** | `gogo.ANY(path, handler)` | 注册所有方法路由 |
### 🌐 主机名路由 (新功能)
支持基于主机名的路由分离,一个服务可以同时处理多个域名的请求。**端口号会自动去除**,确保相同主机名在不同端口上的行为一致。
| 方法 | 语法 | 描述 |
|------|------|------|
| **带主机路由** | `router.RegHTTPProcFuncWithHost(host, method, path, handler)` | 为特定主机注册路由 |
| **带主机静态** | `router.RegHTTPPublicWithHost(host, pattern, path)` | 为特定主机注册静态文件 |
| **带主机转发** | `router.RegHTTPForwardWithHost(host, method, pattern, target)` | 为特定主机注册转发规则 |
| **带主机状态** | `router.RegHTTPStatusFuncWithHost(host, status, handler)` | 为特定主机注册状态页面 |
**使用示例:**
```go
router := gogo.NewHttpRouterHandler()
// 默认主机路由(向后兼容)
router.RegHTTPProcFunc("GET", "/", homeHandler)
// API域名路由 - 端口号会被自动忽略
router.RegHTTPProcFuncWithHost("api.example.com", "GET", "/users", usersHandler)
router.RegHTTPProcFuncWithHost("api.example.com", "POST", "/users", createUserHandler)
// 管理后台域名路由
router.RegHTTPProcFuncWithHost("admin.example.com", "GET", "/dashboard", dashboardHandler)
router.RegHTTPStatusFuncWithHost("admin.example.com", 404, adminNotFoundHandler)
// 静态文件域名
router.RegHTTPPublicWithHost("static.example.com", "/assets", "./static")
```
**端口号自适应处理:**
- `api.example.com:3009` → 匹配 `api.example.com` 路由
- `api.example.com:8080` → 匹配 `api.example.com` 路由
- `api.example.com` → 匹配 `api.example.com` 路由
这使得同一份路由配置可以在开发、测试、生产等不同端口环境下正常工作。
### 🌐 服务启动
| 方法 | 语法 | 描述 |
|------|------|------|
| **HTTP** | `gogo.StartHTTP(port)` | 启动GoGoV2的HTTP服务 |
| **HTTPS** | `gogo.StartHTTPS(port, cert, key)` | 启动启动GoGoV2的HTTPS服务 |
| **HTTP v3** | `gogo.StartHTTPV3(port, threads)` | 启动GoGoV3的HTTP/HTTPS服务 |
| **WebSocket** | `gogo.StartWS(port)` | 启动启动GoGoV2的WebSocket服务 |
### 📡 WebSocket API
| 方法 | 语法 | 描述 |
|------|------|------|
| **发送全局** | `gogo.WebSocketSendToAll(data)` | 向所有客户端发送 |
| **发送分组** | `gogo.WebSocketSendToGroup(data, group)` | 向指定分组发送 |
| **设置分组** | `conn.SetGroup(group)` | 设置连接分组 |
### 🗄️ 数据库操作
| 方法 | 语法 | 描述 |
|------|------|------|
| **初始化** | `gogo.SQLInit(driver, dsn, max, idle)` | 初始化数据库连接 |
| **查询** | `gogo.SQLQuery(sql, args...)` | 执行查询 |
| **插入** | `gogo.SQLInsert(table, data)` | 插入数据 |
| **更新** | `gogo.SQLUpdate(table, where, data)` | 更新数据 |
| **删除** | `gogo.SQLDelete(table, where)` | 删除数据 |
### 🔐 认证系统
| 方法 | 语法 | 描述 |
|------|------|------|
| **Basic认证** | `gogo.BasicAuth(validateFunc)` | HTTP Basic认证 |
| **预处理路由** | `gogo.GET_PRE(path, middleware, handler)` | 带中间件的路由 |
## 🤝 贡献指南
### 🎯 如何贡献
1. **🍴 Fork** 项目到您的GitHub账户
2. **🌿 创建** 功能分支: `git checkout -b feature/amazing-feature`
3. **💻 提交** 您的更改: `git commit -m 'Add amazing feature'`
4. **📤 推送** 到分支: `git push origin feature/amazing-feature`
5. **🔄 提交** Pull Request
### 📋 开发规范
- **代码风格**: 遵循 Go 官方编码规范
- **测试覆盖**: 新功能需要包含单元测试
- **文档更新**: 更新相关文档和示例
- **兼容性**: 保持向后兼容性
### 🐛 报告问题
在提交Issue前,请确保:
- [ ] 搜索了现有的Issues
- [ ] 提供了复现步骤
- [ ] 包含了环境信息
- [ ] 使用了Issue模板
### 📝 开发环境
```bash
# 克隆项目
git clone https://gitee.com/konyshe/gogo.git
cd gogo
# 安装依赖
go mod tidy
# 运行测试
go test ./...
# 运行示例
go run examples/http/main.go
```
## 📄 许可证
本项目采用 [MIT](https://gitee.com/konyshe/gogo) 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。
## 🙏 致谢
感谢所有为 GoGo 框架做出贡献的开发者!
## 📞 联系我们
- 📧 邮箱: 2312708932@qq.com
- 🐛 问题反馈: [Issues](https://gitee.com/konyshe/gogo/issues)
- 💬 讨论区: [Discussions](https://gitee.com/konyshe/gogo/discussions)
- 📚 文档: [Wiki](https://gitee.com/konyshe/gogo/wiki)
---
**⭐ 如果这个项目对您有帮助,请给个Star!**