services.go
type TokenDetail struct{
Token *string
TokenDetail *iapi.LoginToken
}
controller.go
func AfterTokenAccountValidation(req interface{}, token string) (interface{}, error) {
// 创建 TokenDetail 实例
tokenDetail := &services.TokenDetail{
Token: &token,
}
// 定义 wrapped_handler 作为 TokenHandler 类型的函数
wrappedHandler := func(req interface{}, token *services.TokenDetail) (interface{}, error) {
reqParams, ok := req.(*iapi.UserStreamerListReq)
if !ok {
return nil, fmt.Errorf("转换类型错误")
}
resp, err := user_streamer_obj.UserStreamerList(reqParams, *token)
return resp, err
}
// 使用 WithTokenAccountValidation 包装 handler 并执行
handler := services.WithTokenAccountValidation(wrappedHandler)
return handler(req, tokenDetail)
}
我想让这个AfterTokenAccountValidation函数更具通用性,比如req.(*iapi.UserStreamerListReq),能换成不同的结构体,user_streamer_obj.UserStreamerList(reqParams, *token)也可以更换,应该怎么做
golang中间件弹性封装
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
4条回答 默认 最新
檀越@新空间 2025-09-27 17:58关注下午好🌅🌅🌅
本答案参考通义千问为了使
AfterTokenAccountValidation函数更具通用性,我们需要将 请求结构体的类型转换 和 业务逻辑的调用 从硬编码中解耦出来。可以通过以下方式实现:
✅ 目标
- 让函数能够处理多种不同的请求结构体(如
*iapi.UserStreamerListReq,*iapi.LoginReq, 等)。 - 允许在调用时动态指定业务逻辑方法(如
user_streamer_obj.UserStreamerList或其他服务方法)。
✅ 解决方案
1. 定义一个通用的处理器函数签名
使用
func(req interface{}, token *services.TokenDetail) (interface{}, error)作为通用的 handler 接口。2. 封装 Token 验证中间件为通用版本
将
WithTokenAccountValidation改造成可以接受任意 handler 的形式。3. 通过闭包或参数传递业务逻辑
将
user_streamer_obj.UserStreamerList替换为一个可配置的函数参数。
✅ 修改后的代码示例
services.go(保持原样,除非需要扩展)
package services type TokenDetail struct { Token *string TokenDetail *iapi.LoginToken } // WithTokenAccountValidation 是一个中间件函数,用于包装带有 Token 验证的 handler func WithTokenAccountValidation(handler func(req interface{}, token *TokenDetail) (interface{}, error)) func(interface{}, *TokenDetail) (interface{}, error) { return func(req interface{}, token *TokenDetail) (interface{}, error) { // 这里可以添加 Token 验证逻辑 if token == nil || token.Token == nil || *token.Token == "" { return nil, fmt.Errorf("无效的 Token") } return handler(req, token) } }
controller.go(修改后的版本)
package controller import ( "fmt" "your_project/iapi" "your_project/services" ) // GenericHandler 是一个通用的 handler 类型,接收 req 和 token,并返回结果和错误 type GenericHandler func(req interface{}, token *services.TokenDetail) (interface{}, error) // AfterTokenAccountValidation 是一个通用的验证函数,支持动态传入业务逻辑 func AfterTokenAccountValidation(req interface{}, token string, handlerFunc GenericHandler) (interface{}, error) { tokenDetail := &services.TokenDetail{ Token: &token, } // 使用中间件包装 handler wrappedHandler := services.WithTokenAccountValidation(handlerFunc) return wrappedHandler(req, tokenDetail) }
✅ 如何调用这个通用函数?
示例 1:调用 UserStreamerList
func HandleUserStreamerList(req interface{}, token *services.TokenDetail) (interface{}, error) { reqParams, ok := req.(*iapi.UserStreamerListReq) if !ok { return nil, fmt.Errorf("类型转换错误") } // 假设 user_streamer_obj 是已初始化的服务对象 resp, err := user_streamer_obj.UserStreamerList(reqParams, *token) return resp, err } // 调用方式 result, err := AfterTokenAccountValidation(req, token, HandleUserStreamerList)示例 2:调用 Login 方法(假设是另一个服务)
func HandleLogin(req interface{}, token *services.TokenDetail) (interface{}, error) { reqParams, ok := req.(*iapi.LoginReq) if !ok { return nil, fmt.Errorf("类型转换错误") } resp, err := auth_service.Login(reqParams, *token) return resp, err } // 调用方式 result, err := AfterTokenAccountValidation(req, token, HandleLogin)
✅ 总结
| 问题 | 解决方案 | |------|----------| |
req.(*iapi.UserStreamerListReq)是硬编码的 | 将其替换为泛型函数,由外部传入 | |user_streamer_obj.UserStreamerList(...)是固定的 | 将其作为参数传入,支持多服务调用 | | 函数不够通用 | 使用闭包和接口设计,提升复用性 |
✅ 最终建议
- 抽象出
GenericHandler类型,统一 handler 接口。 - 使用闭包或函数参数 来灵活切换业务逻辑。
- 保持中间件逻辑独立,只做 Token 验证,不涉及具体业务逻辑。
如果你有多个类似的业务方法,也可以进一步封装成通用的服务调用器。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 让函数能够处理多种不同的请求结构体(如