Go:使用Gin 编写简单的 RESTful Web 服务 API

405 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情


目标:构建Http服务器,处理get和post请求

Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架

准备工作

定义一个struct,用来存储数据; 像是json:"id"这种标签,指定了序列化为json数据时的字段名,没有的话就会使用结构体字段的大写名称(这样就不太符合JSON的格式了);

type album struct {
   ID     string  `json:"id"`
   Title  string  `json:"title"`
   Artist string  `json:"artist"`
   Price  float64 `json:"price"`
}

定义切片,提供数据

var albums = []album{
   {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
   {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
   {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}

写一个GET请求的处理器,返回所有数据

当客户端发出GET /albums的请求时,以json格式返回数据;

  • gin.Context带有请求参数,负责验证和序列化json数据等等;
  • c.IndentedJSON将数据序列化成json,并添加到response中去;第一个参数是想发送给客户端的HTTP状态码,第二个参数是要序列化成json的数据;
  • 可以替换成c.JSON 来发送更紧凑的json数据
func getAlbums(c *gin.Context) {
   c.IndentedJSON(http.StatusOK, albums)
}
  • 初始化一个gin路由器;
  • 将/albums路径上的GET方法与getAlbums函数连接起来;
  • 将路由器连接到http.Server上,并启动服务器;
func main(){
   router := gin.Default()
   router.GET("/albums", getAlbums)
   router.Run("localhost:8080")
}

go run .运行服务器;再打开另一个窗口运行curl http://localhost:8080/albums

image.png

添加一个POST请求的处理器

当客户端向/albums发出POST请求时,把请求体中的数据添加到现有切片中;

  • 添加一个处理POST请求的函数;
  • c.BindJSON将请求体中的数据绑定到newAlbum变量;
  • 将数据添加到切片中;
  • 将HTTP状态码201 http.StatusCreated 和添加的数据添加到respons中;
func postAlbums(c *gin.Context) {
        var newAlbum album
        // Call BindJSON to bind the received JSON to newAlbum.
        if err := c.BindJSON(&newAlbum); err != nil {
                return
        }
        albums = append(albums, newAlbum)
        c.IndentedJSON(http.StatusCreated, newAlbum)
}

将/albums路径上的POST方法与postAlbums函数连接起来;main函数中添加以下语句;

router.POST("/albums", postAlbums)
  • 运行go run .
  • 使用另一个窗口运行: curl http://localhost:8080/albums --include --header "Content-Type: application/json" --request "POST" --data '{"id": "4","title": "The Modern Sound of Betty Carter","artist": "Betty Carter","price": 49.99}'

结果: image.png

添加一个处理程序来返回一个特定的数据

当客户端发出GET/albums/[id]的请求时,返回ID与路径参数id相匹配的数据。

  • 使用gin.Context.Param来检索URL中的id路径参数;
  • 当把这个处理程序映射到一个路径时,这个路径中将包括一个参数的占位符;
  • 循环切片中的数据,寻找ID与参数id匹配的数据;如果找到了,将这条数据序列化成json数据,并返回200状态码;如果没找到,返回404状态码
func getAlbumByID(c *gin.Context) {
        id := c.Param("id")
        // Loop over the list of albums, looking for
        // an album whose ID value matches the parameter.
        for _, a := range albums {
                if a.ID == id {
                        c.IndentedJSON(http.StatusOK, a)
                        return
                }
        }
        c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}

/albums/:id路径与getAlbumByID函数连接起来;

在Gin中,路径中某个item前面的冒号表示这是一个路径参数;

router.GET("/albums/:id", getAlbumByID)

image.png

数据不存在时

curl http://localhost:8080/albums/5
{
    "message": "album not found"
}

至此,一个简单的RESTful web service就完成了。

补充