【问题标题】:golang call handler inside a handler处理程序内的 golang 调用处理程序
【发布时间】:2023-02-21 19:23:15
【问题描述】:

我想使用现有的处理程序而不实际发送 http 请求(http.Do 或类似的东西),所以我使用 gin.CreateTestContext(httptest.NewRecorder()) 创建新的 *gin.Context 来调用现有的 Accept 处理程序。

我已经尝试使用 c.Copy() 来复制 AcceptOrders 上下文并使用它们来调用现有的 Accept 处理程序,但是当在现有的 Accept 处理程序上调用 c.JSON 时我会感到恐慌

我也尝试使用不带副本的 c 传递给现有的 Accept 处理程序,但我无法覆盖 c.JSON,因为它已经在现有的 Accept 处理程序上被调用

有没有更好的方法来实现我想要的(在另一个处理程序中调用现有处理程序)?

感谢您的答复

func (cms *CmsOrderHandler) AcceptOrders(c *gin.Context) {
var referenceIds constant.OrderReferenceIDs
err := c.Bind(&referenceIds)
if err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
        "error":   "bad_request",
        "message": err.Error(),
    })
    return
}

if len(referenceIds.ReferenceIds) == 0 {
    c.JSON(http.StatusBadRequest, gin.H{
        "error":   "bad_request",
        "message": err.Error(),
    })
    return
}

for _, referenceId := range referenceIds.ReferenceIds {
    r := httptest.NewRecorder()
    gin.SetMode(gin.ReleaseMode)
    cCopy, _ := gin.CreateTestContext(r)
    req, err := http.NewRequest(http.MethodPost, "", nil)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "error":   "internal server error",
            "message": err.Error(),
        })
        return
    }
    cCopy.Params = append(c.Params, gin.Param{Key: "reference_id", Value: referenceId})
    cCopy.Request = req
    cms.Accept(cCopy)
}

c.JSON(http.StatusOK, gin.H{})
}

【问题讨论】:

  • “在处理程序中调用处理程序”-- 对我来说听起来像个坏主意;为什么不将 Accept 处理程序的逻辑转换为不依赖于 gin 上下文的普通函数,然后从 Accept 和 AcceptOrders 调用该函数?
  • @mkopriva,我可以,但是我想避免很多变化,我能知道为什么这对你来说不是个好主意吗?
  • 原则上这是个坏主意。如果您在为 API 构造参数时遇到问题,则说明您没有使用适当的 API。在生产代码中依赖测试包(httptest.NewRecorder、gin.CreateTestContext)是可疑的。这些东西不符合相同的标准;例如,他们经常恐慌而不是优雅地处理错误。此外, http.NewRequest 创建出站请求,而不是服务器请求。有一些细微的差异可能会在某个时候回来咬你。
  • “我能知道原因吗”-- 原因是它不能像您已经了解到的那样开箱即用。处理程序(和它们的中间件)旨在处理它们自己的请求,它们不应该在它们之间分工。这就是设计。你违背了设计。即使您尝试做的事情是可能的,它仍然是错误的。每当您不得不诉诸恶作剧时,这都是一个坏主意。使用正确的工具来完成工作。
  • 感谢@mkopriva 的回复。我会按照您的建议将 Accept 处理程序逻辑转换为普通函数,并从 Accept 和 AcceptOrders 中调用它

标签: rest go http go-gin


【解决方案1】:

@mkopriva 和@Peter 在评论中回答,谢谢!

【讨论】:

    猜你喜欢
    • 2016-04-10
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多