目录

Prerequisites  前提条件

Design API endpoints  设计API终节点

Create a folder for your code  为你的代码创建文件夹

Create the data  创建数据

Write a handler to return all items  编写一个处理器来返回所有项

Write a handler to add a new item  编写一个处理器来增加新项

Write a handler to return a specific item  编写一个处理器来返回特定项

Completed code  完整代码

This tutorial introduces the basics of writing a RESTful web service API with Go and the Gin Web Framework (Gin).

本教程介绍使用Go和Gin Web Framework(Gin)编写RESTful web service API的基本知识。

You’ll get the most out of this tutorial if you have a basic familiarity with Go and its tooling. If this is your first exposure to Go, please see Tutorial: Get started with Go for a quick introduction.

如果你对Go和它的工具已经有基本了解,将在本章中充分发挥。如果这是你首次面对Go,请看教程:从Go开始,作为快速介绍。

Gin simplifies many coding tasks associated with building web applications, including web services. In this tutorial, you’ll use Gin to route requests, retrieve request details, and marshal JSON for responses.

Gin简化许多与构建web应用相关编码任务,包括web services。在本教程中,你将使用Gin来路由请求,检索请求细节,并将响应解析为JSON。

In this tutorial, you will build a RESTful API server with two endpoints. Your example project will be a repository of data about vintage jazz records.

在本教程中,你将构建一个有两个终节点的RESTful API server。你的示例项目将是关于古典爵士乐唱片的数据存储库。

The tutorial includes the following sections:

本教程包括以下部分:

  1. Design API endpoints.  设计API终节点
  2. Create a folder for your code.  为你的代码创建文件夹
  3. Create the data.  创建数据
  4. Write a handler to return all items.  编写一个处理器来返回所有项
  5. Write a handler to add a new item.  编写一个处理器来增加新项
  6. Write a handler to return a specific item.  编写一个处理器来返回特定项

Note: For other tutorials, see Tutorials.

注意:其它教程,请看教程。

To try this as an interactive tutorial you complete in Google Cloud Shell, click the button below.

要在谷歌云Shell上以交互方式试用此教程,点击后面的按钮。

Open in Cloud Shell

Prerequisites  前提条件

  • An installation of Go 1.16 or later. For installation instructions, see Installing Go.  安装1.16以上版本的Go。对于安装说明,请看安装Go。
  • A tool to edit your code. Any text editor you have will work fine.  编辑代码的工具。任何称手的文本编辑器。
  • A command terminal. Go works well using any terminal on Linux and Mac, and on PowerShell or cmd in Windows.  一个命令终端。使用Linux或Mac上的任何终端和Windows上的PowerShell,Go工作的都很好。
  • The curl tool. On Linux and Mac, this should already be installed. On Windows, it’s included on Windows 10 Insider build 17063 and later. For earlier Windows versions, you might need to install it. For more, see Tar and Curl Come to Windows.  curl工具。在Linux和Mac上,它应该已经安装。对于Windows,它被包括在Windows 10 insider build 17063或以上版本。对于Windows的早期版本,你可能需要安装。更多信息,请看Windows上的Tar和Curl。

Design API endpoints  设计API终节点

You’ll build an API that provides access to a store selling vintage recordings on vinyl. So you’ll need to provide endpoints through which a client can get and add albums for users.

你将构建一个访问销售古典乐唱片的商店的API。这样,你将需要提供终节点,客户端可以通过终节点为用户获取或增加专辑。

When developing an API, you typically begin by designing the endpoints. Your API’s users will have more success if the endpoints are easy to understand.

当开发API时,你通常以设计终节点开始。如果终节点易于理解,你的API的用户将取得更大的成功。

Here are the endpoints you’ll create in this tutorial.

这里是本教程中你将创建的终节点。

/albums

GETPOST

/albums/:id

GET

Next, you’ll create a folder for your code.

将下来,你将为即将编写的代码创建文件夹。

Create a folder for your code  为即将编写的代码创建文件夹

To begin, create a project for the code you’ll write.  开始,为即将编写的代码创建一个项目。

$ cd
C:\> cd %HOMEPATH%
$ mkdir web-service-gin
$ cd web-service-gin
$ go mod init example/web-service-gin
go: creating new go.mod: module example/web-service-gin

Next, you’ll design data structures for handling data.

接下来,你将为处理数据设计数据结构。

Create the data  创建数据

To keep things simple for the tutorial, you’ll store data in memory. A more typical API would interact with a database.

为使本教程简单化,你将在内存中存储数据。通常,API与数据库交互。

Note that storing data in memory means that the set of albums will be lost each time you stop the server, then recreated when you start it.

注意,在内存中存储数据,专辑集将在每次停止服务后丢失,然后在启动服务时重建。

Write the code  编码

package main
// album represents data about a record album.
type album struct {
    ID     string  `json:"id"`
    Title  string  `json:"title"`
    Artist string  `json:"artist"`
    Price  float64 `json:"price"`
}
// albums slice to seed record album data.
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},
}

Next, you’ll write code to implement your first endpoint.

接下来,你将编码实现你的首个终节点。

Write a handler to return all items  编写返回所有项的处理器

GET /albums

当客户端发出GET /albums请求,你想要以JSON返回所有专辑。

To do this, you’ll write the following:

要这样做,你将编写以下代码:

  • Logic to prepare a response  准备响应的逻辑
  • Code to map the request path to your logic  映射请求路径到你的逻辑的代码

Note that this is the reverse of how they’ll be executed at runtime, but you’re adding dependencies first, then the code that depends on them.

注意,这与它们执行时的顺序是相反的,但是你首先增加依赖,然后增加依赖它们的代码。

Write the code  编码

// getAlbums responds with the list of all albums as JSON.
func getAlbums(c *gin.Context) {
    c.IndentedJSON(http.StatusOK, albums)
}
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)

    router.Run("localhost:8080")
}
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

Run the code  运行代码

$ go get .
go get: added github.com/gin-gonic/gin v1.7.2
$ go run .
$ curl http://localhost:8080/albums
[
        {
                "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
        }
]
POST

你已经启动了一个API!在接下来的部分中,你将使用创建另一个终节点,这个终节点处理POST请求并增加一个新专辑。

Write a handler to add a new item  编写处理器添加新项

POST/albums

当客户端发起POST /albums请求,你想要将请求主体中描述的专辑添加到已有的专辑数据中。

To do this, you’ll write the following:

要做到这样,你将编写以下代码:

POST

Write the code  编码

// postAlbums adds an album from JSON received in the request body.
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
    }

    // Add the new album to the slice.
    albums = append(albums, newAlbum)
    c.IndentedJSON(http.StatusCreated, newAlbum)
}
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}

Run the code  运行代码

$ 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}'
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Date: Wed, 02 Jun 2021 00:34:12 GMT
Content-Length: 116

{
    "id": "4",
    "title": "The Modern Sound of Betty Carter",
    "artist": "Betty Carter",
    "price": 49.99
}
$ curl http://localhost:8080/albums \
    --header "Content-Type: application/json" \
    --request "GET"
[
        {
                "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
        },
        {
                "id": "4",
                "title": "The Modern Sound of Betty Carter",
                "artist": "Betty Carter",
                "price": 49.99
        }
]
GET

在接下来的部分中,你将增加处理获取某个特定专辑的代码。

Write a handler to return a specific item  编写一个处理器返回特定专辑

GET /albums/[id]id

当客户端请求GET /albums/[id]时,你想要返回ID匹配路径参数id的专辑。

To do this, you will:  要这样做,你将:

  • Add logic to retrieve the requested album.  增加检索请求的专辑的逻辑
  • Map the path to the logic.  映射路径到逻辑。

Write the code  编码

// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
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"})
}
func main() {
    router := gin.Default()
    router.GET("/albums", getAlbums)
    router.GET("/albums/:id", getAlbumByID)
    router.POST("/albums", postAlbums)

    router.Run("localhost:8080")
}

Run the code  运行代码

$ go run .
$ curl http://localhost:8080/albums/2
{
        "id": "2",
        "title": "Jeru",
        "artist": "Gerry Mulligan",
        "price": 17.99
}

Conclusion  结论

Congratulations! You’ve just used Go and Gin to write a simple RESTful web service.

恭喜!你已经使用Go和Gin编写了一个简单的RESTful web service。

Suggested next topics:  推荐下一个主题:

Completed code  完整代码

This section contains the code for the application you build with this tutorial.  本节包含本教程构建的应用的代码。