Golang Gin一个路由处理不同查询的方法

huangapple go评论85阅读模式
英文:

golang gin one route for different queries

问题

在gin中,可以使用:item(名称)或:id来定义一个路由吗?

示例:

r.GET("/inventories/(:item|:id)", controllers.FindInventory)

然后我可以这样做...

func FindInventory(g *gin.Context) {
    var inv models.Inventory

    if item {
       err := models.DB.Where("item = ?", g.Param("item")).First(&inv).Error
    } else {
       err := models.DB.Where("id = ?", g.Param("id")).First(&inv).Error
    }
       
    if err != nil {
        g.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
        return
    }

    g.JSON(http.StatusOK, gin.H{"data": inv})
}

或者是否有一种方法可以在一个路由中处理两种类型的查询?

英文:

is it possible in gin to have one route with either :item (name) OR :id?

example:

r.GET("/inventories/(:item|:id)", controllers.FindInventory)

Then I could probably do something like ...

func FindInventory(g *gin.Context) {
	var inv models.Inventory

    if item:
       err := models.DB.Where("item = ?", g.Param("item")).First(&inv).Error
    else:
       err := models.DB.Where("id = ?", g.Param("id")).First(&inv).Error
       
	if err != nil {
		g.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
		return
	}

	g.JSON(http.StatusOK, gin.H{"data": inv})
}

or is there a way to use one route for two types of queries ?

答案1

得分: 3

不,不支持这样做。但是一定有一种方法可以区分项目和ID。所以很容易自己实现这个逻辑。

像这样:

r.GET("/inventories/:item", controllers.FindInventory)
func FindInventory(g *gin.Context) {
	var inv models.Inventory

	item := g.Param("item")
	id, err := strconv.Atoi(item)
	if err != nil {
		err := models.DB.Where("item = ?", item).First(&inv).Error
	} else {
		err := models.DB.Where("id = ?", id).First(&inv).Error
	}
	if err != nil {
		g.JSON(http.StatusBadRequest, gin.H{"error": "记录未找到!"})
		return
	}

	g.JSON(http.StatusOK, gin.H{"data": inv})
}

但是如果无法区分的话,你需要有两个单独的请求路径,如下:

  • /inventories/by-item/:item
  • /inventories/by-id/:id

2023-05-31更新:将@EpicAdidash和@boyvinall的评论合并到答案中。谢谢!

英文:

No, this is not supported. But there must be some way to distinguish between an item and an id. So it's easy to implement the logic yourself.

Like this:

r.GET("/inventories/:item", controllers.FindInventory)
func FindInventory(g *gin.Context) {
	var inv models.Inventory

	item := g.Param("item")
	id, err := strconv.Atoi(item)
	if err != nil {
		err := models.DB.Where("item = ?", item).First(&inv).Error
	} else {
		err := models.DB.Where("id = ?", id).First(&inv).Error
	}
	if err != nil {
		g.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
		return
	}

	g.JSON(http.StatusOK, gin.H{"data": inv})
}

But if it's not possible to distinguish, then you'd need to have two separate request paths like

  • /inventories/by-item/:item
  • and /inventories/by-id/:id

Update on 2023-05-31: merged @EpicAdidash's and @boyvinall's comments into the answer. Thank you!

答案2

得分: 0

是的,你可以使用参数来实现这一点,但首先要确保项目的数据和ID是不同的,否则你就必须使用查询来实现。

英文:

Yes you can do that with params but the first thing is that data of item and id should be different otherwise you have to resort to queries to do that

huangapple
  • 本文由 发表于 2023年5月27日 13:13:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76345419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定