type Operator struct{
LogTag string
}
func NewOperator() *Operator{
obj := new(Operator)
obj.LogTag = "services.admin"
return obj
}
func (o *Operator) List(req *iapi.OperatorListReq, token *string)(resp iapi.OperatorListResp,err error){
token_detail,err := ParseToken(token)
if err != nil{
return
}
return
}
func (o *Operator) Add(req *iapi.OperatorAddReq, token *string)(resp iapi.OperatorAddResp,err error){
token_detail,err := ParseToken(token)
if err != nil{
return
}
return
}
ParseToken为检查函数,每次执行操作必须要经过这个函数,但我不想每个函数里都这么调用,能否将这个函数写个中间件
golang调用函数中间件
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
5条回答 默认 最新
檀越@新空间 2025-09-23 16:49关注下午好🌅🌅🌅
本答案参考通义千问在 Go 语言中,虽然没有像其他语言(如 Python 或 Node.js)那样的“中间件”机制,但你可以通过函数组合或装饰器模式来实现类似“中间件”的功能。这样可以避免在每个方法中重复调用
ParseToken函数。
✅ 解决方案
1. 定义一个通用的中间件函数
你可以创建一个包装函数,用于执行
ParseToken检查,并返回结果。这个函数可以接受一个操作函数作为参数,然后在其前后执行检查逻辑。func WithAuth(fn func(*Operator, *iapi.OperatorListReq, *string) (iapi.OperatorListResp, error)) func(*Operator, *iapi.OperatorListReq, *string) (iapi.OperatorListResp, error) { return func(o *Operator, req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error) { token_detail, err := ParseToken(token) if err != nil { // 如果解析失败,直接返回错误 return nil, err } // 执行原始函数 return fn(o, req, token) } }重点: 这个
WithAuth中间件函数将ParseToken的逻辑封装起来,可以在多个操作中复用。
2. 使用中间件包装你的方法
你可以在调用
List和Add方法时,使用WithAuth来包装它们,从而避免在每个方法内部重复写ParseToken。// 原始方法 func (o *Operator) List(req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error) { // 不再需要 ParseToken return iapi.OperatorListResp{}, nil } func (o *Operator) Add(req *iapi.OperatorAddReq, token *string) (iapi.OperatorAddResp, error) { // 不再需要 ParseToken return iapi.OperatorAddResp{}, nil }然后,你在调用这些方法时使用中间件:
func CallList(o *Operator, req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error) { return WithAuth(o.List)(o, req, token) } func CallAdd(o *Operator, req *iapi.OperatorAddReq, token *string) (iapi.OperatorAddResp, error) { return WithAuth(o.Add)(o, req, token) }重点: 通过这种方式,你可以将认证逻辑集中处理,提高代码可维护性。
3. 进一步优化:使用接口和泛型(Go 1.18+)
如果你希望更通用一些,可以考虑使用泛型来支持不同类型的请求和响应。
type HandlerFunc[T any, R any] func(*Operator, T, *string) (R, error) func WithAuth[T any, R any](fn HandlerFunc[T, R]) HandlerFunc[T, R] { return func(o *Operator, req T, token *string) (R, error) { token_detail, err := ParseToken(token) if err != nil { var zero R return zero, err } return fn(o, req, token) } }然后在方法中使用:
func (o *Operator) List(req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error) { return iapi.OperatorListResp{}, nil } // 调用方式: resp, err := WithAuth(func(o *Operator, req *iapi.OperatorListReq, token *string) (iapi.OperatorListResp, error) { return o.List(req, token) })(o, req, token)重点: 使用泛型可以让中间件更加灵活,适用于不同的方法。
✅ 总结
| 步骤 | 内容 | |------|------| | 1 | 定义一个通用的中间件函数
WithAuth,用于封装ParseToken逻辑 | | 2 | 在调用方法前使用WithAuth包装原方法,避免重复代码 | | 3 | 可选:使用泛型提高灵活性,适配不同类型的方法 |
✅ 示例代码(完整版)
package main import ( "fmt" ) // 假设的类型定义 type Operator struct { LogTag string } type OperatorListReq struct{} type OperatorListResp struct{} type OperatorAddReq struct{} type OperatorAddResp struct{} // ParseToken 是验证 Token 的函数 func ParseToken(token *string) (interface{}, error) { if token == nil || *token == "" { return nil, fmt.Errorf("invalid token") } return "valid", nil } // 中间件函数 func WithAuth[T any, R any](fn func(*Operator, T, *string) (R, error)) func(*Operator, T, *string) (R, error) { return func(o *Operator, req T, token *string) (R, error) { tokenDetail, err := ParseToken(token) if err != nil { var zero R return zero, err } return fn(o, req, token) } } // 原始方法 func (o *Operator) List(req *OperatorListReq, token *string) (OperatorListResp, error) { fmt.Println("List method called") return OperatorListResp{}, nil } func (o *Operator) Add(req *OperatorAddReq, token *string) (OperatorAddResp, error) { fmt.Println("Add method called") return OperatorAddResp{}, nil } // 使用中间件调用方法 func CallList(o *Operator, req *OperatorListReq, token *string) (OperatorListResp, error) { return WithAuth(o.List)(o, req, token) } func CallAdd(o *Operator, req *OperatorAddReq, token *string) (OperatorAddResp, error) { return WithAuth(o.Add)(o, req, token) } func main() { operator := &Operator{} token := "valid_token" resp, err := CallList(operator, &OperatorListReq{}, token) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("List response:", resp) } respAdd, err := CallAdd(operator, &OperatorAddReq{}, token) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Add response:", respAdd) } }重点: 通过上述方式,你可以将
ParseToken集中处理,避免重复代码,提升代码可读性和可维护性。本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报