在Golang中的动态类型转换

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

Dynamic casting in Golang

问题

所以...我正在使用Gin框架为我的想法创建一个RESTful API,我遇到了以下问题 -
假设我有以下端点:

/a/:id/*action /b/:id/*action /c/:id/*action
显然,当我没有提供任何操作时,我希望返回给定ID的数据。也就是说,我只是查询一些数据并返回它,这意味着功能基本相同,只有返回的数据不同。

这是我的一个示例代码 -

   func GetBusiness(c *gin.Context) {                                                                                                                                                                                     
       businessID, err := strconv.Atoi(c.Param("id"))                                                                                                                                                                                  
       if businessID == 0 || err != nil {                                                                                                                                                                                               
           c.JSON(http.StatusBadRequest, gin.H{"success": false, "errorMessage": "Missing ID"})                                                                                                                                         
       }                                                                                                                                                                                                                                 
       business := &Business{}                                                                                                                                                                                                           
       business, err = business.Get(businessID)                                                                                                                                                                                         
       if err != nil {                                                                                                                                                                                                                  
           c.JSON(http.StatusBadRequest, gin.H{"success": false, "errorMessage": "Business not found"})                                                                                                                                
       }                                                                                                                                                                                                                                
      c.JSON(http.StatusOK, business)                                                                                                                                                                                                   
   }   

显然,business可以变成user或其他任何东西。所以,在这个冗长的阐述之后,我对你们的问题是,我如何在这种情况下防止代码重复?我尝试使用接口,但我仍然在努力理解Go的面向对象特性,所以我真的很感激任何帮助。

提前感谢!

英文:

So... I'm creating a RESTful API for my idea using Gin framework and I've came into the following problem -
Let's say that I've got the following endpoints:

/a/:id/*action
/b/:id/*action
/c/:id/*action

So, obviously, when I'm not giving any action then I want to return the data for the given ID. Meaning, I'm doing nothing but querying some data and returning it, this means that the functionality is basically the same and only the returned data is different.

Here's an example code of mine -

   func GetBusiness(c *gin.Context) {                                                                                                                                                                                     
       businessID, err := strconv.Atoi(c.Param("id"))                                                                                                                                                                                  
       if businessID == 0 || err != nil {                                                                                                                                                                                               
           c.JSON(http.StatusBadRequest, gin.H{"success": false, "errorMessage": "Missing ID"})                                                                                                                                         
       }                                                                                                                                                                                                                                 
       business := &Business{}                                                                                                                                                                                                           
       business, err = business.Get(businessID)                                                                                                                                                                                         
       if err != nil {                                                                                                                                                                                                                  
           c.JSON(http.StatusBadRequest, gin.H{"success": false, "errorMessage": "Business not found"})                                                                                                                                
       }                                                                                                                                                                                                                                
      c.JSON(http.StatusOK, business)                                                                                                                                                                                                   
   }   

So, obviously, business can become user or anything else. So, after this long exposition, my question to you goers, is, how can I prevent code duplication in this kind of situation? I've tried using an interface but I'm still struggling with the OO nature of Go, so I would really appriciate any help.

Thanks in advance!

答案1

得分: 5

有几件事情可以减少代码重复,但不幸的是,在Go语言中,由于其显式错误处理和缺乏面向对象特性,你总是需要编写一些样板代码(这并不一定是坏事!)。

所以我目前唯一的建议是将常见功能放在中间件处理程序中,并对代码进行一些重构,例如:

parseIdMiddleware := func(c *gin.Context) {
  id, err := strconv.Atoi(c.Param("id"))
  if businessID == 0 || err != nil {
    c.AbortWithError(http.StatusBadRequest, errors.New("Missing ID"))
    return
  }
  c.Set("id", id)
}
...
gin.Use(gin.ErrorLogger(), parseIdMiddleware)

并重写你的处理程序:

func GetBusiness(c *gin.Context) {
  id := c.MustGet("id").(int)
  business, err := store.GetBusiness(id)
  if err != nil {
    c.AbortWithError(http.StatusBadRequest, err)
    return // 不要忘记这个!
  }
  c.JSON(http.StatusOK, business)
}

还有,像往常一样,阅读其他人的代码!我推荐你看一下 https://github.com/drone/drone。这应该能给你一个很好的代码结构概述。

英文:

There are a few things you can do to reduce code duplication, but unfortunately, you will always be writing some boilerplate in go, because of it's explicit error handling and lack of OOP-ness. (which is not necessarily a bad thing!).

So my only suggestions at the moment is to put common functionality in middleware handlers and restructure your code a litte, for example:

parseIdMiddleware := func(c *gin.Context) {
  id, err := strconv.Atoi(c.Param("id"))
  if businessID == 0 || err != nil {
    c.AbortWithError(http.StatusBadRequest, errors.New("Missing ID"))
    return
  }
  c.Set("id", id)
}
...
gin.Use(gin.ErrorLogger(), parseIdMiddleware)

and rewrite your handlers to

func GetBusiness(c *gin.Context) {
  id := c.MustGet("id").(int)
  business, err := store.GetBusiness(id)
  if err != nil {
    c.AbortWithError(http.StatusBadRequest, err)
    return // don't forget this!
  }
  c.JSON(http.StatusOK, business)
}

And as always, read other people's code! I recommend https://github.com/drone/drone. That should give you a pretty good overview of how to structure your code.

huangapple
  • 本文由 发表于 2016年1月31日 21:20:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/35114289.html
匿名

发表评论

匿名网友

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

确定