修改包依赖名称
This commit is contained in:
36
README.md
36
README.md
@@ -30,8 +30,24 @@
|
|||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
|
### 1. 配置私有仓库(重要)
|
||||||
|
|
||||||
|
由于本项目使用私有 Git 仓库,需要先配置 `GOPRIVATE` 环境变量:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go get github.com/go-common
|
# 使用 go env 命令配置(推荐,永久生效)
|
||||||
|
go env -w GOPRIVATE=git.toowon.com
|
||||||
|
|
||||||
|
# 验证配置
|
||||||
|
go env GOPRIVATE
|
||||||
|
```
|
||||||
|
|
||||||
|
**详细配置说明请参考 [SETUP.md](./SETUP.md)**
|
||||||
|
|
||||||
|
### 2. 安装模块
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get git.toowon.com/jimmy/go-commom
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用示例
|
## 使用示例
|
||||||
@@ -50,7 +66,7 @@ go get github.com/go-common
|
|||||||
|
|
||||||
#### 数据库迁移
|
#### 数据库迁移
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/migration"
|
import "git.toowon.com/jimmy/go-commom/migration"
|
||||||
|
|
||||||
migrator := migration.NewMigrator(db)
|
migrator := migration.NewMigrator(db)
|
||||||
migrator.AddMigration(migration.Migration{
|
migrator.AddMigration(migration.Migration{
|
||||||
@@ -65,7 +81,7 @@ migrator.Up()
|
|||||||
|
|
||||||
#### 日期转换
|
#### 日期转换
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/datetime"
|
import "git.toowon.com/jimmy/go-commom/datetime"
|
||||||
|
|
||||||
datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
||||||
now := datetime.Now()
|
now := datetime.Now()
|
||||||
@@ -74,7 +90,7 @@ str := datetime.FormatDateTime(now)
|
|||||||
|
|
||||||
#### HTTP响应
|
#### HTTP响应
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/http"
|
import "git.toowon.com/jimmy/go-commom/http"
|
||||||
|
|
||||||
http.Success(w, data)
|
http.Success(w, data)
|
||||||
http.SuccessPage(w, list, total, page, pageSize)
|
http.SuccessPage(w, list, total, page, pageSize)
|
||||||
@@ -84,8 +100,8 @@ http.Error(w, 1001, "业务错误")
|
|||||||
#### 中间件
|
#### 中间件
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CORS + 时区中间件
|
// CORS + 时区中间件
|
||||||
@@ -101,7 +117,7 @@ timezone := http.GetTimezone(r)
|
|||||||
|
|
||||||
#### 配置管理
|
#### 配置管理
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/config"
|
import "git.toowon.com/jimmy/go-commom/config"
|
||||||
|
|
||||||
// 从文件加载配置
|
// 从文件加载配置
|
||||||
cfg, err := config.LoadFromFile("./config.json")
|
cfg, err := config.LoadFromFile("./config.json")
|
||||||
@@ -114,7 +130,7 @@ corsConfig := cfg.GetCORS()
|
|||||||
|
|
||||||
#### 文件上传和查看
|
#### 文件上传和查看
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/storage"
|
import "git.toowon.com/jimmy/go-commom/storage"
|
||||||
|
|
||||||
// 创建存储实例
|
// 创建存储实例
|
||||||
storage, _ := storage.NewStorage(storage.StorageTypeOSS, cfg)
|
storage, _ := storage.NewStorage(storage.StorageTypeOSS, cfg)
|
||||||
@@ -132,7 +148,7 @@ proxyHandler := storage.NewProxyHandler(storage)
|
|||||||
|
|
||||||
#### 邮件发送
|
#### 邮件发送
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/email"
|
import "git.toowon.com/jimmy/go-commom/email"
|
||||||
|
|
||||||
// 从配置创建邮件发送器
|
// 从配置创建邮件发送器
|
||||||
mailer, _ := email.NewEmail(cfg.GetEmail())
|
mailer, _ := email.NewEmail(cfg.GetEmail())
|
||||||
@@ -147,7 +163,7 @@ mailer.SendSimple(
|
|||||||
|
|
||||||
#### 短信发送
|
#### 短信发送
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/sms"
|
import "git.toowon.com/jimmy/go-commom/sms"
|
||||||
|
|
||||||
// 从配置创建短信发送器
|
// 从配置创建短信发送器
|
||||||
smsClient, _ := sms.NewSMS(cfg.GetSMS())
|
smsClient, _ := sms.NewSMS(cfg.GetSMS())
|
||||||
|
|||||||
174
SETUP.md
Normal file
174
SETUP.md
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# 项目配置说明
|
||||||
|
|
||||||
|
## GOPRIVATE 环境变量配置
|
||||||
|
|
||||||
|
由于本项目使用私有 Git 仓库 (`git.toowon.com`),需要配置 `GOPRIVATE` 环境变量,让 Go 工具链知道这些模块是私有的,不要通过公共代理下载。
|
||||||
|
|
||||||
|
### 配置方法
|
||||||
|
|
||||||
|
#### 方法一:临时配置(当前终端会话有效)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# macOS/Linux
|
||||||
|
export GOPRIVATE=git.toowon.com
|
||||||
|
|
||||||
|
# Windows (PowerShell)
|
||||||
|
$env:GOPRIVATE="git.toowon.com"
|
||||||
|
|
||||||
|
# Windows (CMD)
|
||||||
|
set GOPRIVATE=git.toowon.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方法二:永久配置(推荐)
|
||||||
|
|
||||||
|
**macOS/Linux:**
|
||||||
|
|
||||||
|
1. 编辑 shell 配置文件(根据你使用的 shell 选择):
|
||||||
|
```bash
|
||||||
|
# 如果是 zsh(macOS 默认)
|
||||||
|
nano ~/.zshrc
|
||||||
|
|
||||||
|
# 如果是 bash
|
||||||
|
nano ~/.bashrc
|
||||||
|
# 或
|
||||||
|
nano ~/.bash_profile
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 添加以下内容:
|
||||||
|
```bash
|
||||||
|
export GOPRIVATE=git.toowon.com
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 保存文件并重新加载配置:
|
||||||
|
```bash
|
||||||
|
# zsh
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
# bash
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
|
||||||
|
1. 打开"系统属性" -> "高级" -> "环境变量"
|
||||||
|
2. 在"用户变量"或"系统变量"中点击"新建"
|
||||||
|
3. 变量名:`GOPRIVATE`
|
||||||
|
4. 变量值:`git.toowon.com`
|
||||||
|
5. 点击"确定"保存
|
||||||
|
|
||||||
|
#### 方法三:使用 go env 命令(推荐,Go 1.13+)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 设置 GOPRIVATE
|
||||||
|
go env -w GOPRIVATE=git.toowon.com
|
||||||
|
|
||||||
|
# 查看当前配置
|
||||||
|
go env GOPRIVATE
|
||||||
|
|
||||||
|
# 如果需要设置多个私有仓库,用逗号分隔
|
||||||
|
go env -w GOPRIVATE=git.toowon.com,github.com/your-org
|
||||||
|
```
|
||||||
|
|
||||||
|
### 验证配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看 GOPRIVATE 配置
|
||||||
|
go env GOPRIVATE
|
||||||
|
|
||||||
|
# 应该输出: git.toowon.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 其他相关环境变量(可选)
|
||||||
|
|
||||||
|
如果需要更细粒度的控制,还可以配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GOPRIVATE: 私有模块,不通过代理下载,不校验 checksum
|
||||||
|
go env -w GOPRIVATE=git.toowon.com
|
||||||
|
|
||||||
|
# GONOPROXY: 不通过代理下载的模块(默认与 GOPRIVATE 相同)
|
||||||
|
go env -w GONOPROXY=git.toowon.com
|
||||||
|
|
||||||
|
# GONOSUMDB: 不校验 checksum 的模块(默认与 GOPRIVATE 相同)
|
||||||
|
go env -w GONOSUMDB=git.toowon.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git 认证配置
|
||||||
|
|
||||||
|
由于是私有仓库,还需要配置 Git 认证:
|
||||||
|
|
||||||
|
#### 方法一:使用 SSH(推荐)
|
||||||
|
|
||||||
|
1. 确保已配置 SSH 密钥
|
||||||
|
2. 使用 SSH URL:
|
||||||
|
```bash
|
||||||
|
git config --global url."git@git.toowon.com:".insteadOf "https://git.toowon.com/"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方法二:使用 HTTPS + 个人访问令牌
|
||||||
|
|
||||||
|
1. 在 Git 服务器上生成个人访问令牌
|
||||||
|
2. 配置 Git 凭据:
|
||||||
|
```bash
|
||||||
|
git config --global credential.helper store
|
||||||
|
```
|
||||||
|
3. 首次访问时会提示输入用户名和令牌
|
||||||
|
|
||||||
|
#### 方法三:在 URL 中包含凭据(不推荐,安全性较低)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在 go.mod 中使用(不推荐)
|
||||||
|
# 或者通过 .netrc 文件配置
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
#### 问题1:go get 失败,提示找不到模块
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
1. 确认 GOPRIVATE 已正确配置
|
||||||
|
2. 确认 Git 认证已配置
|
||||||
|
3. 尝试手动克隆仓库验证:
|
||||||
|
```bash
|
||||||
|
git clone git@git.toowon.com:jimmy/go-commom.git
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 问题2:go mod download 失败
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
# 清除模块缓存
|
||||||
|
go clean -modcache
|
||||||
|
|
||||||
|
# 重新下载
|
||||||
|
go mod download
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 问题3:IDE 无法识别模块
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
1. 重启 IDE
|
||||||
|
2. 在 IDE 中执行:`go mod tidy`
|
||||||
|
3. 确认 IDE 的 Go 环境变量配置正确
|
||||||
|
|
||||||
|
### 完整配置示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 配置 GOPRIVATE
|
||||||
|
go env -w GOPRIVATE=git.toowon.com
|
||||||
|
|
||||||
|
# 2. 配置 Git SSH(如果使用 SSH)
|
||||||
|
git config --global url."git@git.toowon.com:".insteadOf "https://git.toowon.com/"
|
||||||
|
|
||||||
|
# 3. 验证配置
|
||||||
|
go env | grep GOPRIVATE
|
||||||
|
|
||||||
|
# 4. 测试模块下载
|
||||||
|
go get git.toowon.com/jimmy/go-commom@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参考文档
|
||||||
|
|
||||||
|
- [Go Modules 官方文档](https://go.dev/ref/mod)
|
||||||
|
- [Go 私有模块配置](https://go.dev/ref/mod#private-modules)
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config 应用配置
|
// Config 应用配置
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
### 安装
|
### 安装
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go get github.com/go-common
|
go get git.toowon.com/jimmy/go-commom
|
||||||
```
|
```
|
||||||
|
|
||||||
### 使用示例
|
### 使用示例
|
||||||
@@ -24,7 +24,7 @@ go get github.com/go-common
|
|||||||
#### 数据库迁移
|
#### 数据库迁移
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/migration"
|
import "git.toowon.com/jimmy/go-commom/migration"
|
||||||
|
|
||||||
migrator := migration.NewMigrator(db)
|
migrator := migration.NewMigrator(db)
|
||||||
migrator.AddMigration(migration.Migration{
|
migrator.AddMigration(migration.Migration{
|
||||||
@@ -40,7 +40,7 @@ migrator.Up()
|
|||||||
#### 日期转换
|
#### 日期转换
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/datetime"
|
import "git.toowon.com/jimmy/go-commom/datetime"
|
||||||
|
|
||||||
datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
||||||
now := datetime.Now()
|
now := datetime.Now()
|
||||||
@@ -50,7 +50,7 @@ str := datetime.FormatDateTime(now)
|
|||||||
#### HTTP响应
|
#### HTTP响应
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/http"
|
import "git.toowon.com/jimmy/go-commom/http"
|
||||||
|
|
||||||
http.Success(w, data)
|
http.Success(w, data)
|
||||||
http.SuccessPage(w, list, total, page, pageSize)
|
http.SuccessPage(w, list, total, page, pageSize)
|
||||||
@@ -61,8 +61,8 @@ http.Error(w, 1001, "业务错误")
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CORS + 时区中间件
|
// CORS + 时区中间件
|
||||||
@@ -79,7 +79,7 @@ timezone := http.GetTimezone(r)
|
|||||||
#### 配置管理
|
#### 配置管理
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/config"
|
import "git.toowon.com/jimmy/go-commom/config"
|
||||||
|
|
||||||
// 从文件加载配置
|
// 从文件加载配置
|
||||||
cfg, err := config.LoadFromFile("./config.json")
|
cfg, err := config.LoadFromFile("./config.json")
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
### 1. 加载配置文件
|
### 1. 加载配置文件
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/config"
|
import "git.toowon.com/jimmy/go-commom/config"
|
||||||
|
|
||||||
// 从文件加载配置(支持绝对路径和相对路径)
|
// 从文件加载配置(支持绝对路径和相对路径)
|
||||||
config, err := config.LoadFromFile("/path/to/config.json")
|
config, err := config.LoadFromFile("/path/to/config.json")
|
||||||
@@ -167,7 +167,7 @@ addr := config.GetRedisAddr()
|
|||||||
corsConfig := config.GetCORS()
|
corsConfig := config.GetCORS()
|
||||||
|
|
||||||
// 使用CORS中间件
|
// 使用CORS中间件
|
||||||
import "github.com/go-common/middleware"
|
import "git.toowon.com/jimmy/go-commom/middleware"
|
||||||
chain := middleware.NewChain(
|
chain := middleware.NewChain(
|
||||||
middleware.CORS(corsConfig),
|
middleware.CORS(corsConfig),
|
||||||
)
|
)
|
||||||
@@ -289,8 +289,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
### 1. 设置默认时区
|
### 1. 设置默认时区
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/datetime"
|
import "git.toowon.com/jimmy/go-commom/datetime"
|
||||||
|
|
||||||
// 设置默认时区为上海时区
|
// 设置默认时区为上海时区
|
||||||
err := datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
err := datetime.SetDefaultTimeZone(datetime.AsiaShanghai)
|
||||||
@@ -401,7 +401,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -428,7 +428,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/email"
|
"git.toowon.com/jimmy/go-commom/email"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 从配置加载
|
// 从配置加载
|
||||||
@@ -107,7 +107,7 @@ if err != nil {
|
|||||||
### 5. 使用Message结构发送(便捷方法)
|
### 5. 使用Message结构发送(便捷方法)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/email"
|
import "git.toowon.com/jimmy/go-commom/email"
|
||||||
|
|
||||||
msg := &email.Message{
|
msg := &email.Message{
|
||||||
To: []string{"to@example.com"},
|
To: []string{"to@example.com"},
|
||||||
@@ -295,8 +295,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/email"
|
"git.toowon.com/jimmy/go-commom/email"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ HTTP Restful工具提供了标准化的HTTP请求和响应处理功能,包含
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 简单成功响应(data为nil)
|
// 简单成功响应(data为nil)
|
||||||
@@ -198,7 +198,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 用户列表接口
|
// 用户列表接口
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ CORS中间件用于处理跨域资源共享,支持:
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -50,7 +50,7 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -131,9 +131,9 @@ corsHandler := middleware.CORS(corsConfig)(handler)
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -162,8 +162,8 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -183,8 +183,8 @@ func main() {
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -240,7 +240,7 @@ X-Timezone: Asia/Shanghai
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -282,9 +282,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -331,8 +331,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
import (
|
import (
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"github.com/go-common/migration"
|
"git.toowon.com/jimmy/go-commom/migration"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 初始化数据库连接
|
// 初始化数据库连接
|
||||||
@@ -135,7 +135,46 @@ for _, s := range status {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. 生成迁移版本号
|
### 6. 重置迁移
|
||||||
|
|
||||||
|
#### 方式一:仅清空迁移记录(不回滚数据库变更)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 直接调用(需要传入确认标志)
|
||||||
|
err := migrator.Reset(true)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交互式确认(推荐,会提示警告信息)
|
||||||
|
err := migrator.ResetWithConfirm()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方式二:回滚所有迁移并清空记录
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 直接调用(需要传入确认标志)
|
||||||
|
err := migrator.ResetAll(true)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交互式确认(推荐,会提示警告信息)
|
||||||
|
err := migrator.ResetAllWithConfirm()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:**
|
||||||
|
- `Reset()` 仅清空迁移记录表,不会回滚已执行的数据库变更
|
||||||
|
- `ResetAll()` 会回滚所有已应用的迁移(执行Down函数),然后清空记录
|
||||||
|
- 交互式方法会显示详细的警告信息,需要输入确认文本才能执行
|
||||||
|
|
||||||
|
### 7. 生成迁移版本号
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// 生成基于时间戳的版本号
|
// 生成基于时间戳的版本号
|
||||||
@@ -194,6 +233,44 @@ type Migration struct {
|
|||||||
|
|
||||||
**返回:** 迁移状态列表和错误信息
|
**返回:** 迁移状态列表和错误信息
|
||||||
|
|
||||||
|
#### Reset(confirm bool) error
|
||||||
|
|
||||||
|
重置所有迁移记录(仅清空记录表,不回滚数据库变更)。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `confirm`: 确认标志,必须为true才能执行
|
||||||
|
|
||||||
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**注意:** 此操作只清空迁移记录,不会回滚已执行的迁移操作。如果需要回滚迁移,请先使用Down方法逐个回滚。
|
||||||
|
|
||||||
|
#### ResetWithConfirm() error
|
||||||
|
|
||||||
|
交互式重置所有迁移记录(带确认提示)。
|
||||||
|
|
||||||
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**说明:** 会显示警告信息,需要输入"RESET"(全大写)才能执行。
|
||||||
|
|
||||||
|
#### ResetAll(confirm bool) error
|
||||||
|
|
||||||
|
重置所有迁移并回滚所有已应用的迁移。
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `confirm`: 确认标志,必须为true才能执行
|
||||||
|
|
||||||
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**注意:** 此操作会回滚所有已应用的迁移(执行Down函数),然后清空迁移记录。操作不可逆,请谨慎使用。
|
||||||
|
|
||||||
|
#### ResetAllWithConfirm() error
|
||||||
|
|
||||||
|
交互式重置所有迁移并回滚(带确认提示)。
|
||||||
|
|
||||||
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**说明:** 会显示警告信息,需要输入"RESET ALL"(全大写)才能执行。
|
||||||
|
|
||||||
### MigrationStatus 结构体
|
### MigrationStatus 结构体
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -230,11 +307,16 @@ type MigrationStatus struct {
|
|||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
1. 迁移版本号必须唯一,建议使用时间戳格式
|
1. **迁移版本号**:必须唯一,建议使用时间戳格式
|
||||||
2. 迁移操作在事务中执行,失败会自动回滚
|
2. **事务支持**:迁移操作在事务中执行,失败会自动回滚
|
||||||
3. 迁移记录表会自动创建,无需手动创建
|
3. **自动创建表**:迁移记录表会自动创建,无需手动创建
|
||||||
4. 如果迁移文件没有对应的down文件,回滚操作会失败
|
4. **回滚文件**:如果迁移文件没有对应的down文件,回滚操作会失败
|
||||||
5. 迁移按版本号升序执行,确保顺序正确
|
5. **执行顺序**:迁移按版本号升序执行,确保顺序正确
|
||||||
|
6. **重置操作**:
|
||||||
|
- `Reset()` 只清空迁移记录,不会回滚数据库变更
|
||||||
|
- `ResetAll()` 会回滚所有迁移,操作不可逆
|
||||||
|
- 建议使用交互式方法(`ResetWithConfirm`、`ResetAllWithConfirm`)以确保安全
|
||||||
|
- 在生产环境使用重置功能前,请确保已备份数据库
|
||||||
|
|
||||||
## 示例
|
## 示例
|
||||||
|
|
||||||
|
|||||||
10
docs/sms.md
10
docs/sms.md
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/sms"
|
"git.toowon.com/jimmy/go-commom/sms"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 从配置加载
|
// 从配置加载
|
||||||
@@ -102,7 +102,7 @@ if err != nil {
|
|||||||
### 5. 使用SendRequest结构发送(便捷方法)
|
### 5. 使用SendRequest结构发送(便捷方法)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/sms"
|
import "git.toowon.com/jimmy/go-commom/sms"
|
||||||
|
|
||||||
req := &sms.SendRequest{
|
req := &sms.SendRequest{
|
||||||
PhoneNumbers: []string{"13800138000", "13900139000"},
|
PhoneNumbers: []string{"13800138000", "13900139000"},
|
||||||
@@ -329,8 +329,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/sms"
|
"git.toowon.com/jimmy/go-commom/sms"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 加载配置
|
// 加载配置
|
||||||
@@ -50,7 +50,7 @@ if err != nil {
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 打开文件
|
// 打开文件
|
||||||
@@ -81,7 +81,7 @@ fmt.Printf("File URL: %s\n", url)
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 创建上传处理器
|
// 创建上传处理器
|
||||||
@@ -125,7 +125,7 @@ curl -X POST http://localhost:8080/upload \
|
|||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 创建代理查看处理器
|
// 创建代理查看处理器
|
||||||
@@ -144,7 +144,7 @@ GET /file?key=images/test.jpg
|
|||||||
### 5. 生成对象键
|
### 5. 生成对象键
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import "github.com/go-common/storage"
|
import "git.toowon.com/jimmy/go-commom/storage"
|
||||||
|
|
||||||
// 生成简单对象键
|
// 生成简单对象键
|
||||||
objectKey := storage.GenerateObjectKey("images/", "test.jpg")
|
objectKey := storage.GenerateObjectKey("images/", "test.jpg")
|
||||||
@@ -288,9 +288,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -344,8 +344,8 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"net/smtp"
|
"net/smtp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Email 邮件发送器
|
// Email 邮件发送器
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
// "gorm.io/driver/mysql"
|
// "gorm.io/driver/mysql"
|
||||||
// "gorm.io/gorm"
|
// "gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/email"
|
"git.toowon.com/jimmy/go-commom/email"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 用户结构
|
// 用户结构
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
"github.com/go-common/http"
|
"git.toowon.com/jimmy/go-commom/http"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 示例:使用CORS和时区中间件
|
// 示例:使用CORS和时区中间件
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"github.com/go-common/migration"
|
"git.toowon.com/jimmy/go-commom/migration"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
105
examples/migration_reset_example.go
Normal file
105
examples/migration_reset_example.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.toowon.com/jimmy/go-commom/migration"
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 初始化数据库连接(使用SQLite作为示例)
|
||||||
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to connect to database:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建迁移器
|
||||||
|
migrator := migration.NewMigrator(db)
|
||||||
|
|
||||||
|
// 添加一些迁移
|
||||||
|
migrator.AddMigrations(
|
||||||
|
migration.Migration{
|
||||||
|
Version: "20240101000001",
|
||||||
|
Description: "create_users_table",
|
||||||
|
Up: func(db *gorm.DB) error {
|
||||||
|
return db.Exec(`
|
||||||
|
CREATE TABLE users (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) UNIQUE NOT NULL
|
||||||
|
)
|
||||||
|
`).Error
|
||||||
|
},
|
||||||
|
Down: func(db *gorm.DB) error {
|
||||||
|
return db.Exec("DROP TABLE IF EXISTS users").Error
|
||||||
|
},
|
||||||
|
},
|
||||||
|
migration.Migration{
|
||||||
|
Version: "20240101000002",
|
||||||
|
Description: "add_created_at_to_users",
|
||||||
|
Up: func(db *gorm.DB) error {
|
||||||
|
return db.Exec("ALTER TABLE users ADD COLUMN created_at DATETIME").Error
|
||||||
|
},
|
||||||
|
Down: func(db *gorm.DB) error {
|
||||||
|
return db.Exec("ALTER TABLE users DROP COLUMN created_at").Error
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// 执行迁移
|
||||||
|
fmt.Println("=== Executing migrations ===")
|
||||||
|
err = migrator.Up()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to run migrations:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看状态
|
||||||
|
fmt.Println("\n=== Migration status ===")
|
||||||
|
status, err := migrator.Status()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to get status:", err)
|
||||||
|
}
|
||||||
|
for _, s := range status {
|
||||||
|
fmt.Printf("Version: %s, Description: %s, Applied: %v\n",
|
||||||
|
s.Version, s.Description, s.Applied)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 示例1:仅清空迁移记录(不回滚数据库变更)
|
||||||
|
fmt.Println("\n=== Example 1: Reset migration records only ===")
|
||||||
|
fmt.Println("Note: This only clears records, not database changes")
|
||||||
|
// 直接调用(需要确认标志)
|
||||||
|
// err = migrator.Reset(true)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal("Failed to reset:", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 交互式确认(推荐)
|
||||||
|
// 取消注释下面的代码来测试交互式重置
|
||||||
|
// err = migrator.ResetWithConfirm()
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal("Failed to reset with confirm:", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 示例2:回滚所有迁移并清空记录
|
||||||
|
fmt.Println("\n=== Example 2: Reset all migrations (rollback + clear records) ===")
|
||||||
|
fmt.Println("Note: This will rollback all migrations and clear records")
|
||||||
|
// 直接调用(需要确认标志)
|
||||||
|
// err = migrator.ResetAll(true)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal("Failed to reset all:", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 交互式确认(推荐)
|
||||||
|
// 取消注释下面的代码来测试交互式重置
|
||||||
|
// err = migrator.ResetAllWithConfirm()
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal("Failed to reset all with confirm:", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
fmt.Println("\nNote: Reset functions are commented out for safety.")
|
||||||
|
fmt.Println("Uncomment the code above to test reset functionality.")
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/sms"
|
"git.toowon.com/jimmy/go-commom/sms"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
"github.com/go-common/storage"
|
"git.toowon.com/jimmy/go-commom/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
7
go.mod
7
go.mod
@@ -1,14 +1,17 @@
|
|||||||
module github.com/go-common
|
module git.toowon.com/jimmy/go-commom
|
||||||
|
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gorm.io/driver/mysql v1.5.2
|
gorm.io/driver/mysql v1.5.2
|
||||||
gorm.io/gorm v1.25.5
|
gorm.io/driver/sqlite v1.6.0
|
||||||
|
gorm.io/gorm v1.30.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
|
golang.org/x/text v0.20.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
10
go.sum
10
go.sum
@@ -5,8 +5,14 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||||
|
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||||
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
||||||
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
||||||
|
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||||
|
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
||||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/go-common/middleware"
|
"git.toowon.com/jimmy/go-commom/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseJSON 解析JSON请求体
|
// ParseJSON 解析JSON请求体
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-common/datetime"
|
"git.toowon.com/jimmy/go-commom/datetime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TimezoneKey context中存储时区的key
|
// TimezoneKey context中存储时区的key
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package migration
|
package migration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -371,3 +372,219 @@ func LoadMigrationsFromFiles(dir string, pattern string) ([]Migration, error) {
|
|||||||
func GenerateVersion() string {
|
func GenerateVersion() string {
|
||||||
return strconv.FormatInt(time.Now().Unix(), 10)
|
return strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset 重置所有迁移(清空迁移记录表)
|
||||||
|
// confirm: 确认标志,必须为true才能执行重置
|
||||||
|
// 注意:此操作会清空所有迁移记录,但不会回滚已执行的迁移操作
|
||||||
|
// 如果需要回滚迁移,请先使用Down方法逐个回滚
|
||||||
|
func (m *Migrator) Reset(confirm bool) error {
|
||||||
|
if !confirm {
|
||||||
|
return fmt.Errorf("reset operation requires explicit confirmation (confirm must be true)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.initTable(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取已应用的迁移数量
|
||||||
|
applied, err := m.getAppliedMigrations()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := len(applied)
|
||||||
|
if count == 0 {
|
||||||
|
fmt.Println("No migrations to reset")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空迁移记录表
|
||||||
|
err = m.db.Exec(fmt.Sprintf("DELETE FROM %s", m.tableName)).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to reset migrations: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Reset completed: %d migration record(s) cleared\n", count)
|
||||||
|
fmt.Println("WARNING: This only clears migration records, not the actual database changes.")
|
||||||
|
fmt.Println("If you need to rollback database changes, use Down() method before reset.")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetWithConfirm 交互式重置所有迁移(带确认提示)
|
||||||
|
// 会提示用户数据会被清空,需要输入确认才能执行
|
||||||
|
func (m *Migrator) ResetWithConfirm() error {
|
||||||
|
if err := m.initTable(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取已应用的迁移数量
|
||||||
|
applied, err := m.getAppliedMigrations()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := len(applied)
|
||||||
|
if count == 0 {
|
||||||
|
fmt.Println("No migrations to reset")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示警告信息
|
||||||
|
fmt.Println("=" + strings.Repeat("=", 60) + "=")
|
||||||
|
fmt.Println("WARNING: This operation will clear all migration records!")
|
||||||
|
fmt.Println("=" + strings.Repeat("=", 60) + "=")
|
||||||
|
fmt.Printf("This will clear %d migration record(s) from the database.\n", count)
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("IMPORTANT NOTES:")
|
||||||
|
fmt.Println(" 1. This operation only clears migration records, NOT the actual database changes.")
|
||||||
|
fmt.Println(" 2. If you need to rollback database changes, use Down() method before reset.")
|
||||||
|
fmt.Println(" 3. After reset, you may need to re-run migrations if the database structure changed.")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Print("Type 'RESET' (all caps) to confirm, or anything else to cancel: ")
|
||||||
|
|
||||||
|
// 读取用户输入
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
input, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read confirmation: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除换行符和空格
|
||||||
|
input = strings.TrimSpace(input)
|
||||||
|
|
||||||
|
// 检查确认
|
||||||
|
if input != "RESET" {
|
||||||
|
fmt.Println("Reset operation cancelled.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行重置
|
||||||
|
return m.Reset(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetAll 重置所有迁移并回滚所有已应用的迁移
|
||||||
|
// confirm: 确认标志,必须为true才能执行
|
||||||
|
// 注意:此操作会回滚所有已应用的迁移,然后清空迁移记录
|
||||||
|
func (m *Migrator) ResetAll(confirm bool) error {
|
||||||
|
if !confirm {
|
||||||
|
return fmt.Errorf("reset all operation requires explicit confirmation (confirm must be true)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.initTable(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取已应用的迁移
|
||||||
|
applied, err := m.getAppliedMigrations()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := len(applied)
|
||||||
|
if count == 0 {
|
||||||
|
fmt.Println("No migrations to reset")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回滚所有已应用的迁移
|
||||||
|
fmt.Printf("Rolling back %d migration(s)...\n", count)
|
||||||
|
|
||||||
|
// 排序迁移(倒序)
|
||||||
|
sort.Slice(m.migrations, func(i, j int) bool {
|
||||||
|
return m.migrations[i].Version > m.migrations[j].Version
|
||||||
|
})
|
||||||
|
|
||||||
|
// 回滚所有已应用的迁移
|
||||||
|
for _, migration := range m.migrations {
|
||||||
|
if !applied[migration.Version] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if migration.Down == nil {
|
||||||
|
fmt.Printf("Warning: Migration %s has no Down function, skipping rollback\n", migration.Version)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始事务
|
||||||
|
tx := m.db.Begin()
|
||||||
|
if tx.Error != nil {
|
||||||
|
return fmt.Errorf("failed to begin transaction: %w", tx.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行回滚
|
||||||
|
if err := migration.Down(tx); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to rollback migration %s: %w", migration.Version, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除迁移记录
|
||||||
|
if err := m.recordMigrationWithDB(tx, migration.Version, migration.Description, false); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
|
if err := tx.Commit().Error; err != nil {
|
||||||
|
return fmt.Errorf("failed to commit rollback %s: %w", migration.Version, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Rolled back migration: %s - %s\n", migration.Version, migration.Description)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Reset all completed: %d migration(s) rolled back and records cleared\n", count)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetAllWithConfirm 交互式重置所有迁移并回滚(带确认提示)
|
||||||
|
// 会提示用户数据会被清空,需要输入确认才能执行
|
||||||
|
func (m *Migrator) ResetAllWithConfirm() error {
|
||||||
|
if err := m.initTable(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取已应用的迁移数量
|
||||||
|
applied, err := m.getAppliedMigrations()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := len(applied)
|
||||||
|
if count == 0 {
|
||||||
|
fmt.Println("No migrations to reset")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示警告信息
|
||||||
|
fmt.Println("=" + strings.Repeat("=", 60) + "=")
|
||||||
|
fmt.Println("WARNING: This operation will rollback ALL migrations and clear records!")
|
||||||
|
fmt.Println("=" + strings.Repeat("=", 60) + "=")
|
||||||
|
fmt.Printf("This will rollback %d migration(s) and clear all migration records.\n", count)
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println("IMPORTANT NOTES:")
|
||||||
|
fmt.Println(" 1. This operation will EXECUTE Down() functions for all applied migrations.")
|
||||||
|
fmt.Println(" 2. All database changes made by migrations will be REVERTED.")
|
||||||
|
fmt.Println(" 3. This operation CANNOT be undone!")
|
||||||
|
fmt.Println(" 4. Make sure you have a database backup before proceeding.")
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Print("Type 'RESET ALL' (all caps) to confirm, or anything else to cancel: ")
|
||||||
|
|
||||||
|
// 读取用户输入
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
input, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read confirmation: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除换行符和空格
|
||||||
|
input = strings.TrimSpace(input)
|
||||||
|
|
||||||
|
// 检查确认
|
||||||
|
if input != "RESET ALL" {
|
||||||
|
fmt.Println("Reset all operation cancelled.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行重置
|
||||||
|
return m.ResetAll(true)
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SMS 短信发送器
|
// SMS 短信发送器
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
commonhttp "github.com/go-common/http"
|
commonhttp "git.toowon.com/jimmy/go-commom/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UploadHandler 文件上传处理器
|
// UploadHandler 文件上传处理器
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MinIOStorage MinIO存储实现
|
// MinIOStorage MinIO存储实现
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OSSStorage OSS存储实现
|
// OSSStorage OSS存储实现
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-common/config"
|
"git.toowon.com/jimmy/go-commom/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Storage 存储接口
|
// Storage 存储接口
|
||||||
|
|||||||
Reference in New Issue
Block a user