添加控制器

在开始为应用添加逻辑前,我们首先需要创建一个控制器并注册路由。还记得之前章节我们使用过的 hello 控制器吗?

        • hello.go
      • hello.go
        • hello_new.go
        • hello_v1_hello.go
        • hello.go
  • 路由注册在 internal/cmd/cmd.go 文件中:

    s.Group("/", func(group *ghttp.RouterGroup) {
        group.Middleware(ghttp.MiddlewareHandlerResponse)
    	group.Bind(
    	    hello.NewV1(),
    	)
    })

    这里使用的方法在 GoFrame 中被称为 规范路由。这种方法很简单,并且可以结合代码生成命令 gf gen ctrl 使用。API 文档也会自动生成,你可以查看 Swagger 页面的 hello 来确认。

    我们推荐使用 规范路由,因为它相较于其他的方式更易于维护和扩展。你也可以在这里了解到其他的路由注册方式。

    创建 API 结构体

    为了使用代码生成命令 gf gen ctrl,你需要先声明 API 结构体。GoFrame 要求的文件结构为 api/{模块}/{版本}/{定义}.go,并且 API 结构体的名称需要以 ReqRes 结尾。让我们遵循 RESTful 的标准来为消息创建一个 API:

    api/message/v1/store.go
    package v1
    
    import "github.com/gogf/gf/v2/frame/g"
    
    type CreateMessageReq struct {
    	g.Meta  `path:"/" tags:"Message" method:"post" sum:"创建一条消息"`
    	UserUid string `json:"user_uid" v:"required|size:10" des:"消息发送人ID" eg:"0000000000"`
    	Content string `json:"content" v:"required|length:1,100" des:"消息内容" eg:"This is my first message."`
    }
    
    type CreateMessageRes struct {
    	g.Meta  `mime:"application/json"`
    	Code    int         `json:"code" v:"required" des:"状态码" eg:"0"`
    	Message string      `json:"message" v:"required" des:"状态消息" eg:"Success"`
    	Data    interface{} `json:"data"`
    }

    这里使用的 g.Meta 可以为 请求响应 添加额外的属性。对于这里的请求,path 用于定义路由,tags 用于设置 OpenAPI 文档中的分组,method 用于声明接受的 HTTP 方法,而 sum 用于添加路由摘要。对于这里的响应,mime 用于设置响应内容的类型。

    结构体中的标签不仅可以用于自动生成 OpenAPI 文档,还可以用于验证或转换数据。例如,v 标签可用于验证请求中的数据。对于我们的请求,UserUID 被设置为必需且长度为10,其他字段类似。你可以在这里找到更多有关数据验证的信息。

    这些标签看起来有些不好理解,不过不用担心,在注册路由后你就能清楚地看到它们的功能了。或者你也可以在这里找到更多有关 gtag 的细节。

    生成控制器

    现在我们可以使用 gf gen ctrl 基于之前声明的结构体来生成控制器:

    & gf gen ctrl
    generated: ...\api\hello\hello.go
    generated: ...\api\message\message.go
    generated: internal\controller\message\message.go
    generated: internal\controller\message\message_new.go
    generated: internal\controller\message\message_v1_create_message.go
    done!

    可以看到它的结构和之前自动生成的 hello 控制器类似。

    ℹ️
    为了避免每次更改完 api 目录下的代码后都要手动运行这个命令,你可以使用一些自动运行插件,例如 VSCode 中的 Run on Save

    打开 internal\controller\message\message_v1_create_message.go,你会看到控制器的具体内容:

    func (c *ControllerV1) CreateMessage(ctx context.Context, req *v1.CreateMessageReq) (res *v1.CreateMessageRes, err error) {
    	return nil, gerror.NewCode(gcode.CodeNotImplemented)
    }

    这里的响应还没有实现,稍后我们会添加一些代码。

    注册路由

    在生成控制器后,我们需要注册路由。打开 internal\cmd 文件夹下的 cmd.go,之前我们使用的 hello 已经在这里注册了:

    internal/cmd/cmd.go
    s.Group("/", func(group *ghttp.RouterGroup) {
    	group.Middleware(ghttp.MiddlewareHandlerResponse)
    	group.Bind(
    		hello.NewV1(),
    	)
    })

    同样,我们可以添加 message 的路由:

    internal/cmd/cmd.go
    s.Group("/messages", func(group *ghttp.RouterGroup) {
    	group.Middleware(ghttp.MiddlewareHandlerResponse)
    	group.Bind(
    		message.NewV1(),
    	)
    })

    由于之前设置的 path/,我们需要在注册路由时为路由组添加 messages。你也可以选择将 path 设置为 /messages,这样就无需在路由组中添加了。

    path/messages 时的路由
    internal/cmd/cmd.go
    s.Group("/", func(group *ghttp.RouterGroup) {
    	group.Middleware(ghttp.MiddlewareHandlerResponse)
    	group.Bind(
    		hello.NewV1(),
    		message.NewV1(),
    	)
    })

    测试

    好!你已经成功的创建了第一个 API 并注册了它的路由。这里是他的 Swagger 页面。

    如果你用过类似 Postman的工具,可以使用下面的请求来测试 API:

    POST http://localhost:8000/messages

    {
      "user_uid": "0000000000",
      "content": "This is my first message."
    }

    或者使用 curl 来测试 API:

    curl -X POST -H "Content-Type: application/json" -d '{"user_uid":"0000000000","content":"This is my first message."}' "http://localhost:8000/messages"

    你会看到类似这样的 Not Implemented 响应:

    {
      "code": 58,
      "message": "Not Implemented",
      "data": null
    }