在之前的教程中,我们设置了一个名为 account 的 Go 应用程序,在 Traefik 反向代理后面自动重新加载,所有这些都在 Docker 开发环境中运行。

在本教程中,我们将使用 gin 设置 http 路由,这将允许我们创建 API 端点来管理用户的帐户。

当我们完成时,您的文件结构应该如下所示。

[最终文件结构](https://res.cloudinary.com/practicaldev/image/fetch/s--tyCsugU---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev- to-uploads.s3.amazonaws.com/i/24lfsz70jadeoveqf3dm.PNG)

仅供参考 - 我已经为Github 存储库中的每个教程创建了一个 git 分支。您可以使用教程 01](https://github.com/JacobSNGoodwin/memrizr/tree/lesson-01)的[分支开始使用我今天使用的相同代码!要启动应用程序,请在顶级目录中运行docker-compose up

如果您愿意,也可以查看视频教程!

添加_Handler_包

首先,让我们在 ~/account 中创建一个名为 handler 的新文件夹。在此文件夹中,创建一个名为 handler.go 的文件。该文件将用于初始化处理程序包。我在这个项目中的约定是用包的名称来命名每个包的“主”文件。

我们在此文件中执行以下操作。

  1. 创建一个 Handler 结构体。这个结构最终将拥有“服务”属性。这些服务包含实现应用程序核心功能的方法。

  2. 我们创建一个 Config 结构体。此配置将包含初始化此 handler 包所需的所有值。

3.一个NewHandler“工厂”函数。此函数用于初始化路由,将从 main 包中调用。

我将在整个项目中使用这个工厂和配置方法,因为它有助于明确每个包需要哪些依赖项。虽然你经常会在其他 Go 项目中看到这一点,但这绝不是标准的。可以直接初始化一个结构。

我们将对在package main内创建的 gin 路由器的引用传递到我们的 handler 包的 Config 中。有了这个参考,我们可以创建一个路由组,它允许我们为我们的端点设置一个通用的“基本 URL”(“/api/account”)。

在这个路由组上,我们将创建一个应该返回基本 JSON 的 get 路由。这个 GET 路由是从我们最初放置在 main.go 中的路由复制和粘贴的。

package handler

import (
    "net/http"

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

// Handler struct holds required services for handler to function
type Handler struct{}

// Config will hold services that will eventually be injected into this
// handler layer on handler initialization
type Config struct {
    R *gin.Engine
}

// NewHandler initializes the handler with required injected services along with http routes
// Does not return as it deals directly with a reference to the gin Engine
func NewHandler(c *Config) {
    // Create a handler (which will later have injected services)
  h := &Handler{} // currently has no properties

    // Create an account group
    g := c.R.Group("/api/account")

    g.GET("/", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "hello": "space persons",
        })
    })
}

在我们测试这段代码之前,请确保从package main中删除 GET 路由处理程序,并将其替换为新创建的package handler的初始化。注意 NewHandler 工厂只是修改了 gin 路由器,并没有返回任何内容。

router := gin.Default()

handler.NewHandler(&handler.Config{
  R: router,
})

srv := &http.Server{
  Addr:    ":8080",
  Handler: router,
}

创建应用程序路由

handler.go 中,我们将在 NewHandler 函数中添加所有路由以及每个路由的相应处理程序方法。随着应用程序的增长,我们最终会将处理函数移动到单独的文件中。

您可以看到每个处理程序方法都返回一些简单的 json,其中“hello”作为键,以及一个告诉哪个处理程序已被调用的值。

func NewHandler(c *Config) {
    // Create an account group
    // Create a handler (which will later have injected services)
    h := &Handler{} // currently has no properties

    // Create a group, or base url for all routes
    g := c.R.Group("/api/account")

    g.GET("/me", h.Me)
    g.POST("/signup", h.Signup)
    g.POST("/signin", h.Signin)
    g.POST("/signout", h.Signout)
    g.POST("/tokens", h.Tokens)
    g.POST("/image", h.Image)
    g.DELETE("/image", h.DeleteImage)
    g.PUT("/details", h.Details)
}

// Me handler calls services for getting
// a user's details
func (h *Handler) Me(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's me",
    })
}

// Signup handler
func (h *Handler) Signup(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's signup",
    })
}

// Signin handler
func (h *Handler) Signin(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's signin",
    })
}

// Signout handler
func (h *Handler) Signout(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's signout",
    })
}

// Tokens handler
func (h *Handler) Tokens(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's tokens",
    })
}

// Image handler
func (h *Handler) Image(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's image",
    })
}

// DeleteImage handler
func (h *Handler) DeleteImage(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's deleteImage",
    })
}

// Details handler
func (h *Handler) Details(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
        "hello": "it's details",
    })
}

随着您的 docker-compose up 运行,您现在应该能够使用您选择的客户端向上述端点发出请求。我使用了很多 Postman,但这里有一个使用命令行 curl 的快速示例。

➜  curl -X GET http://malcorp.test/api/account/me
{"hello":"it's me"}%
➜  curl -X POST http://malcorp.test/api/account/signin
{"hello":"it's signin"}%

使用环境变量配置基本 URL

我们要将基本 url/api/account添加到环境变量中。我们现在将这样做,以便稍后设置环境变量变得轻而易举!

要设置项目范围的环境变量,让我们在根 memrizr 目录中创建一个“.env.dev”文件。

ACCOUNT_API_URL=/api/account

我还建议创建一个 .gitignore 文件并添加“.env.dev”作为条目,以便从您的存储库中省略该文件(最终我们将添加一些您不希望在线结束的凭据)。

然后我们可以将这个环境变量注入到 docker-compose.yml 文件中定义的 account 服务中,如下所示。现在帐户应用程序将可以访问添加到 .env.dev 的任何环境变量!这只是在 Docker 或 Docker Compose 中创建环境变量的一种方式。

 account:
    ...
    ...
    env_file: .env.dev

最后,我们需要告诉应用程序在 handler.go 中使用这个环境变量。为了使这个工作,更新 Group 的参数名称以获取我们刚刚设置的环境变量。

// Create a group, or base url for all routes
    g := c.R.Group(os.Getenv("ACCOUNT_API_URL"))

现在您可以使用docker-compose up重新启动应用程序,然后重新运行上述 curl 命令(或在您选择的客户端中)。

下次

既然我们已经创建了路由,我们就有了一个从外部世界进入我们的应用程序的入口点。这让我们准备好讨论应用程序架构并构建应用程序的各个层。

直到下一个教程!

Logo

云原生社区为您提供最前沿的新闻资讯和知识内容

更多推荐