将工厂改成黑盒模式,降低用户使用成本
This commit is contained in:
@@ -4,9 +4,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.toowon.com/jimmy/go-common/factory"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -16,80 +17,148 @@ func main() {
|
||||
log.Fatal("Failed to create factory:", err)
|
||||
}
|
||||
|
||||
// 直接获取数据库对象(已初始化,可直接使用)
|
||||
ctx := context.Background()
|
||||
|
||||
// ========== 日志记录(黑盒模式,推荐) ==========
|
||||
fac.LogInfo("应用启动")
|
||||
fac.LogDebug("调试信息: %s", "test")
|
||||
fac.LogWarn("警告信息")
|
||||
fac.LogError("错误信息: %v", fmt.Errorf("test error"))
|
||||
|
||||
// 带字段的日志
|
||||
fac.LogInfof(map[string]interface{}{
|
||||
"user_id": 123,
|
||||
"ip": "192.168.1.1",
|
||||
}, "用户登录成功")
|
||||
|
||||
fac.LogErrorf(map[string]interface{}{
|
||||
"error_code": 1001,
|
||||
"user_id": 123,
|
||||
}, "登录失败: %v", fmt.Errorf("invalid password"))
|
||||
|
||||
// ========== 邮件发送(黑盒模式,推荐) ==========
|
||||
err = fac.SendEmail(
|
||||
[]string{"user@example.com"},
|
||||
"验证码",
|
||||
"您的验证码是:123456",
|
||||
)
|
||||
if err != nil {
|
||||
fac.LogError("发送邮件失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("邮件发送成功")
|
||||
}
|
||||
|
||||
// HTML邮件
|
||||
err = fac.SendEmail(
|
||||
[]string{"user@example.com"},
|
||||
"欢迎",
|
||||
"纯文本内容",
|
||||
"<h1>HTML内容</h1>",
|
||||
)
|
||||
if err != nil {
|
||||
fac.LogError("发送HTML邮件失败: %v", err)
|
||||
}
|
||||
|
||||
// ========== 短信发送(黑盒模式,推荐) ==========
|
||||
resp, err := fac.SendSMS(
|
||||
[]string{"13800138000"},
|
||||
map[string]string{"code": "123456"},
|
||||
)
|
||||
if err != nil {
|
||||
fac.LogError("发送短信失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("短信发送成功: %s", resp.RequestID)
|
||||
}
|
||||
|
||||
// 指定模板代码
|
||||
resp, err = fac.SendSMS(
|
||||
[]string{"13800138000"},
|
||||
map[string]string{"code": "123456"},
|
||||
"SMS_123456789", // 模板代码
|
||||
)
|
||||
if err != nil {
|
||||
fac.LogError("发送短信失败: %v", err)
|
||||
}
|
||||
|
||||
// ========== 文件上传(黑盒模式,推荐,自动选择OSS或MinIO) ==========
|
||||
file, err := os.Open("test.jpg")
|
||||
if err == nil {
|
||||
defer file.Close()
|
||||
|
||||
url, err := fac.UploadFile(ctx, "images/test.jpg", file, "image/jpeg")
|
||||
if err != nil {
|
||||
fac.LogError("上传文件失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("文件上传成功: %s", url)
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 获取文件URL(黑盒模式) ==========
|
||||
// 永久有效
|
||||
url, err := fac.GetFileURL("images/test.jpg", 0)
|
||||
if err != nil {
|
||||
fac.LogError("获取文件URL失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("文件URL: %s", url)
|
||||
}
|
||||
|
||||
// 临时访问URL(1小时后过期)
|
||||
url, err = fac.GetFileURL("images/test.jpg", 3600)
|
||||
if err != nil {
|
||||
fac.LogError("获取临时URL失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("临时URL: %s", url)
|
||||
}
|
||||
|
||||
// ========== Redis操作(黑盒模式,推荐) ==========
|
||||
// 设置值(不过期)
|
||||
err = fac.RedisSet(ctx, "user:123", "value")
|
||||
if err != nil {
|
||||
fac.LogError("Redis设置失败: %v", err)
|
||||
}
|
||||
|
||||
// 设置值(带过期时间)
|
||||
err = fac.RedisSet(ctx, "user:123", "value", time.Hour)
|
||||
if err != nil {
|
||||
fac.LogError("Redis设置失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取值
|
||||
value, err := fac.RedisGet(ctx, "user:123")
|
||||
if err != nil {
|
||||
fac.LogError("Redis获取失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("Redis值: %s", value)
|
||||
}
|
||||
|
||||
// 删除键
|
||||
err = fac.RedisDelete(ctx, "user:123", "user:456")
|
||||
if err != nil {
|
||||
fac.LogError("Redis删除失败: %v", err)
|
||||
}
|
||||
|
||||
// 检查键是否存在
|
||||
exists, err := fac.RedisExists(ctx, "user:123")
|
||||
if err != nil {
|
||||
fac.LogError("Redis检查失败: %v", err)
|
||||
} else {
|
||||
fac.LogInfo("键是否存在: %v", exists)
|
||||
}
|
||||
|
||||
// ========== 数据库操作 ==========
|
||||
db, err := fac.GetDatabase()
|
||||
if err != nil {
|
||||
log.Printf("Database not available: %v", err)
|
||||
fac.LogError("数据库连接失败: %v", err)
|
||||
} else {
|
||||
// 直接使用数据库
|
||||
// 直接使用GORM
|
||||
var count int64
|
||||
if err := db.Table("users").Count(&count).Error; err != nil {
|
||||
log.Printf("Failed to count users: %v", err)
|
||||
fac.LogError("查询用户数量失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("User count: %d\n", count)
|
||||
fac.LogInfo("用户数量: %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
// 直接获取Redis客户端(已初始化,可直接使用)
|
||||
redisClient, err := fac.GetRedisClient()
|
||||
if err != nil {
|
||||
log.Printf("Redis not available: %v", err)
|
||||
} else {
|
||||
// 直接使用Redis客户端
|
||||
ctx := context.Background()
|
||||
val, err := redisClient.Get(ctx, "test_key").Result()
|
||||
if err != nil && err != redis.Nil {
|
||||
log.Printf("Redis error: %v", err)
|
||||
} else if err == redis.Nil {
|
||||
fmt.Println("Redis key not found")
|
||||
} else {
|
||||
fmt.Printf("Redis value: %s\n", val)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取邮件客户端(已初始化,可直接使用)
|
||||
emailClient, err := fac.GetEmailClient()
|
||||
if err != nil {
|
||||
log.Printf("Email client not available: %v", err)
|
||||
} else {
|
||||
// 直接使用
|
||||
err = emailClient.SendSimple(
|
||||
[]string{"recipient@example.com"},
|
||||
"测试邮件",
|
||||
"这是测试内容",
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("Failed to send email: %v", err)
|
||||
} else {
|
||||
fmt.Println("Email sent successfully")
|
||||
}
|
||||
}
|
||||
|
||||
// 获取短信客户端(已初始化,可直接使用)
|
||||
smsClient, err := fac.GetSMSClient()
|
||||
if err != nil {
|
||||
log.Printf("SMS client not available: %v", err)
|
||||
} else {
|
||||
// 直接使用
|
||||
resp, err := smsClient.SendSimple(
|
||||
[]string{"13800138000"},
|
||||
map[string]string{"code": "123456"},
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("Failed to send SMS: %v", err)
|
||||
} else {
|
||||
fmt.Printf("SMS sent: %s\n", resp.RequestID)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日志记录器(已初始化,可直接使用)
|
||||
logger, err := fac.GetLogger()
|
||||
if err != nil {
|
||||
log.Printf("Logger not available: %v", err)
|
||||
} else {
|
||||
logger.Info("Application started")
|
||||
logger.Debug("Debug message")
|
||||
logger.Warn("Warning message")
|
||||
logger.Error("Error message")
|
||||
}
|
||||
fac.LogInfo("示例执行完成")
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"git.toowon.com/jimmy/go-common/http"
|
||||
)
|
||||
|
||||
// 用户结构
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取分页参数
|
||||
page, pageSize := http.GetPaginationParams(r)
|
||||
|
||||
// 获取查询参数
|
||||
keyword := http.GetQuery(r, "keyword", "")
|
||||
|
||||
// 模拟查询数据
|
||||
users := []User{
|
||||
{ID: 1, Name: "User1", Email: "user1@example.com"},
|
||||
{ID: 2, Name: "User2", Email: "user2@example.com"},
|
||||
}
|
||||
total := int64(100)
|
||||
|
||||
// 返回分页响应
|
||||
http.SuccessPage(w, users, total, page, pageSize)
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
||||
// 解析请求体
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
if err := http.ParseJSON(r, &req); err != nil {
|
||||
http.BadRequest(w, "请求参数解析失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 参数验证
|
||||
if req.Name == "" {
|
||||
http.Error(w, 1001, "用户名不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 模拟创建用户
|
||||
user := User{
|
||||
ID: 1,
|
||||
Name: req.Name,
|
||||
Email: req.Email,
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
http.SuccessWithMessage(w, "创建成功", user)
|
||||
}
|
||||
|
||||
// 获取用户详情
|
||||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取查询参数
|
||||
id := http.GetQueryInt64(r, "id", 0)
|
||||
|
||||
if id == 0 {
|
||||
http.BadRequest(w, "用户ID不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 模拟查询用户
|
||||
if id == 1 {
|
||||
user := User{ID: 1, Name: "User1", Email: "user1@example.com"}
|
||||
http.Success(w, user)
|
||||
} else {
|
||||
http.Error(w, 1002, "用户不存在")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
GetUserList(w, r)
|
||||
case http.MethodPost:
|
||||
CreateUser(w, r)
|
||||
default:
|
||||
http.NotFound(w, "方法不支持")
|
||||
}
|
||||
})
|
||||
|
||||
http.HandleFunc("/user", GetUser)
|
||||
|
||||
log.Println("Server started on :8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
109
examples/http_handler_example.go
Normal file
109
examples/http_handler_example.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||||
)
|
||||
|
||||
// 用户结构
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// 获取用户列表(使用Handler黑盒模式)
|
||||
func GetUserList(h *commonhttp.Handler) {
|
||||
// 获取分页参数(简洁方式)
|
||||
pagination := h.ParsePaginationRequest()
|
||||
page := pagination.GetPage()
|
||||
pageSize := pagination.GetSize()
|
||||
|
||||
// 获取查询参数(简洁方式)
|
||||
_ = h.GetQuery("keyword", "") // 示例:获取查询参数
|
||||
|
||||
// 模拟查询数据
|
||||
users := []User{
|
||||
{ID: 1, Name: "User1", Email: "user1@example.com"},
|
||||
{ID: 2, Name: "User2", Email: "user2@example.com"},
|
||||
}
|
||||
total := int64(100)
|
||||
|
||||
// 返回分页响应(简洁方式)
|
||||
h.SuccessPage(users, total, page, pageSize)
|
||||
}
|
||||
|
||||
// 创建用户(使用Handler黑盒模式)
|
||||
func CreateUser(h *commonhttp.Handler) {
|
||||
// 解析请求体(简洁方式)
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
if err := h.ParseJSON(&req); err != nil {
|
||||
h.WriteJSON(http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 参数验证
|
||||
if req.Name == "" {
|
||||
h.Error(1001, "用户名不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 模拟创建用户
|
||||
user := User{
|
||||
ID: 1,
|
||||
Name: req.Name,
|
||||
Email: req.Email,
|
||||
}
|
||||
|
||||
// 返回成功响应(简洁方式)
|
||||
h.SuccessWithMessage("创建成功", user)
|
||||
}
|
||||
|
||||
// 获取用户详情(使用Handler黑盒模式)
|
||||
func GetUser(h *commonhttp.Handler) {
|
||||
// 获取查询参数(简洁方式)
|
||||
id := h.GetQueryInt64("id", 0)
|
||||
|
||||
if id == 0 {
|
||||
h.WriteJSON(http.StatusBadRequest, 400, "用户ID不能为空", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 模拟查询用户
|
||||
if id == 1 {
|
||||
user := User{ID: 1, Name: "User1", Email: "user1@example.com"}
|
||||
h.Success(user)
|
||||
} else {
|
||||
h.Error(1002, "用户不存在")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 方式1:使用HandleFunc包装器(推荐,最简洁)
|
||||
http.HandleFunc("/users", commonhttp.HandleFunc(func(h *commonhttp.Handler) {
|
||||
switch h.Request().Method {
|
||||
case http.MethodGet:
|
||||
GetUserList(h)
|
||||
case http.MethodPost:
|
||||
CreateUser(h)
|
||||
default:
|
||||
h.WriteJSON(http.StatusMethodNotAllowed, 405, "方法不支持", nil)
|
||||
}
|
||||
}))
|
||||
|
||||
// 方式2:手动创建Handler(需要更多控制时)
|
||||
http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
|
||||
h := commonhttp.NewHandler(w, r)
|
||||
GetUser(h)
|
||||
})
|
||||
|
||||
log.Println("Server started on :8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
|
||||
61
examples/http_pagination_example.go
Normal file
61
examples/http_pagination_example.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||||
)
|
||||
|
||||
// ListUserRequest 用户列表请求(包含分页字段)
|
||||
type ListUserRequest struct {
|
||||
Keyword string `json:"keyword"`
|
||||
commonhttp.PaginationRequest // 嵌入分页请求结构
|
||||
}
|
||||
|
||||
// User 用户结构
|
||||
type User struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// 获取用户列表(使用Handler和PaginationRequest)
|
||||
func GetUserList(h *commonhttp.Handler) {
|
||||
var req ListUserRequest
|
||||
|
||||
// 方式1:从JSON请求体解析(分页字段会自动解析)
|
||||
if h.Request().Method == http.MethodPost {
|
||||
if err := h.ParseJSON(&req); err != nil {
|
||||
h.WriteJSON(http.StatusBadRequest, 400, "请求参数解析失败", nil)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// 方式2:从查询参数解析分页
|
||||
pagination := h.ParsePaginationRequest()
|
||||
req.PaginationRequest = *pagination
|
||||
req.Keyword = h.GetQuery("keyword", "")
|
||||
}
|
||||
|
||||
// 使用分页方法
|
||||
page := req.GetPage() // 获取页码(默认1)
|
||||
size := req.GetSize() // 获取每页数量(默认20,最大100)
|
||||
_ = req.GetOffset() // 计算偏移量
|
||||
|
||||
// 模拟查询数据
|
||||
users := []User{
|
||||
{ID: 1, Name: "User1", Email: "user1@example.com"},
|
||||
{ID: 2, Name: "User2", Email: "user2@example.com"},
|
||||
}
|
||||
total := int64(100)
|
||||
|
||||
// 返回分页响应
|
||||
h.SuccessPage(users, total, page, size)
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/users", commonhttp.HandleFunc(GetUserList))
|
||||
|
||||
log.Println("Server started on :8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"git.toowon.com/jimmy/go-common/datetime"
|
||||
"git.toowon.com/jimmy/go-common/http"
|
||||
commonhttp "git.toowon.com/jimmy/go-common/http"
|
||||
"git.toowon.com/jimmy/go-common/middleware"
|
||||
)
|
||||
|
||||
@@ -31,8 +31,11 @@ func main() {
|
||||
middleware.Timezone,
|
||||
)
|
||||
|
||||
// 定义处理器
|
||||
handler := chain.ThenFunc(apiHandler)
|
||||
// 定义处理器(使用Handler模式)
|
||||
handler := chain.ThenFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
h := commonhttp.NewHandler(w, r)
|
||||
apiHandler(h)
|
||||
})
|
||||
|
||||
// 注册路由
|
||||
http.Handle("/api", handler)
|
||||
@@ -42,10 +45,10 @@ func main() {
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
|
||||
// apiHandler 处理API请求
|
||||
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 从context获取时区
|
||||
timezone := http.GetTimezone(r)
|
||||
// apiHandler 处理API请求(使用Handler模式)
|
||||
func apiHandler(h *commonhttp.Handler) {
|
||||
// 从Handler获取时区
|
||||
timezone := h.GetTimezone()
|
||||
|
||||
// 使用时区进行时间处理
|
||||
now := datetime.Now(timezone)
|
||||
@@ -53,7 +56,7 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
endOfDay := datetime.EndOfDay(now, timezone)
|
||||
|
||||
// 返回响应
|
||||
http.Success(w, map[string]interface{}{
|
||||
h.Success(map[string]interface{}{
|
||||
"message": "Hello from API",
|
||||
"timezone": timezone,
|
||||
"currentTime": datetime.FormatDateTime(now),
|
||||
@@ -61,4 +64,3 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
"endOfDay": datetime.FormatDateTime(endOfDay),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user