跳到主要内容
版本:2.8.x(Latest)

准备好数据模型后,就可以使用我们的”三板斧“法则开发用户接口了。

添加Api


api/users/v1/users.go

package v1

import "github.com/gogf/gf/v2/frame/g"

type RegisterReq struct {
g.Meta `path:"users/register" method:"post"`
Username string `json:"username"`
Password string `json:"password"`
Email string `json:"email"`
}

type RegisterRes struct {
}

为了更好的维护接口,通常会在接口地址的前面加上版本号。GoFrame推荐使用多级目录管理版本,这个接口的版本号是v1

RegisterReqRegisterRes分别定义HTTP的请求对象和响应对象。g.Meta内嵌到请求结构体中,并通过Go Tag方式来定义一般的接口属性。这段代码意味着我们新增了一个用户注册的接口,接口地址为/users/register,请求方式为POST,并且拥有三个请求参数:UsernamePasswordEmail

执行命令生成Api对应的Controller

$ gf gen ctrl
generated: D:\project\star\api\users\users.go
generated: internal\controller\users\users.go
generated: internal\controller\users\users_new.go
generated: internal\controller\users\users_v1_register.go
done!

这里生成的四个文件,我们只需要关注users_v1_register.go即可,它用作接收HTTP请求,并调用Logic完成业务流程。

如果你已经安装了GoFrame Helper插件,会自动执行gf gen ctrl命令。也可以使用官网提供自动生成方式:教程配置

编写Logic


Logic 是业务逻辑层,存放在internal/logic下,供Controller调用从而实现具体的业务逻辑。

internal/logic/users/register.go

package users

import (
"context"

"star/internal/dao"
"star/internal/model/do"
)

func Register(ctx context.Context, username, password, email string) error {
_, err := dao.Users.Ctx(ctx).Data(do.Users{
Username: username,
Password: password,
Email: email,
}).Insert()
if err != nil {
return err
}
return nil
}

dao.Users是前面生成的数据访问对象,通过它与数据库交互。do.Users是生成的数据模型,它用作数据入库,还有一个类似的数据模型entity.Users用作数据出库。

Controller调用Logic


Controller 层负责接收 Req 请求对象后调用一个或多个Logic完成业务逻辑,一些简单的逻辑也可以直接放在Controller中处理。处理完成后的结果封装在约定的 Res 数据结构中返回。这里的Res数据结构为空,返回nil即可。

internal/controller/users/users_v1_register.go

package users

import (
"context"

"star/internal/logic/users"

"star/api/users/v1"
)

func (c *ControllerV1) Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) {
err = users.Register(ctx, req.Username, req.Password, req.Email)
return nil, err
}

注册控制器


所有的控制器都必须要在cmd中注册才能生效。cmd 层负责引导程序启动,显著的工作是初始化逻辑、注册路由对象、启动 server 监听、阻塞运行程序直至 server 退出。

internal/cmd/cmd.go

package cmd

···

var (
Main = gcmd.Command{
Name: "main",
Usage: "main",
Brief: "start http server",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
group.Middleware(ghttp.MiddlewareHandlerResponse)
group.Group("/v1", func(group *ghttp.RouterGroup) {
group.Bind(
users.NewV1(),
)
})
})
s.Run()
return nil
},
}
)

group.Group 是框架提供的分组路由注册方式,也是框架推荐的注册方式。我们在前面加上v1对应api目录,方便接口版本管理。

运行项目


$ gf run main.go
build: .\main.go
go build -o .\main.exe .\main.go
.\main.exe
build running pid: 8648
2024-11-08 10:36:48.013 [INFO] pid[8648]: http server started listening on [:8000]
2024-11-08 10:36:48.013 [INFO] {e05c16b565dd0518360ebe639e1c623d} swagger ui is serving at address: http://127.0.0.1:8000/swagger/
2024-11-08 10:36:48.014 [INFO] {e05c16b565dd0518360ebe639e1c623d} openapi specification is serving at address: http://127.0.0.1:8000/api.json

ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
----------|--------|--------------------|---------------------------------------------------------|----------------------------------
:8000 | ALL | /api.json | github.com/gogf/gf/v2/net/ghttp.(*Server).openapiSpec |
----------|--------|--------------------|---------------------------------------------------------|----------------------------------
:8000 | ALL | /swagger/* | github.com/gogf/gf/v2/net/ghttp.(*Server).swaggerUI | HOOK_BEFORE_SERVE
----------|--------|--------------------|---------------------------------------------------------|----------------------------------
:8000 | POST | /v1/users/register | star/internal/controller/users.(*ControllerV1).Register | ghttp.MiddlewareHandlerResponse
----------|--------|--------------------|---------------------------------------------------------|----------------------------------

运行结果中打印出了三个接口地址。/swagger/api.json是框架生成的接口文档地址,我们会在2.5 - 接口文档详细的说明它。另外一个地址/v1/users/register便是我们开发出来的用户注册接口。发起一个POST请求来测试它。

$ curl -X POST http://127.0.0.1:8000/v1/users/register -H "Content-Type: application/json" -d "{\"username\":\"oldme\", \"password\":\"123456\", \"email\":\"tyyn1022@gmail.com\"}"

{
"code":0,
"message":"",
"data":null
}

code0代表成功,去数据库查看是否插入了一条数据:

SELECT * FROM users;
IDUsernamePasswordEmailCreated_AtUpdated_At
1oldme123456tyyn1022@gmail.com2024-11-08 10:36:482024-11-08 10:36:48

Created_AtUpdated_At是两个约定字段,会被ORM自动维护,分别代表创建时间和修改时间。