准备好数据模型后,就可以使用我们的"三板斧"法则开发用户接口了。
添加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
。
RegisterReq
和RegisterRes
分别定义HTTP
的请求对象和响应对象。g.Meta
内嵌到请求结构体中,并通过Go Tag
方式来定义一般的接口属性。这段代码意味着我们新增了一个用户注册的接口,接口地址为/users/register
,请求方式为POST
,并且拥有三个请求参数:Username
、Password
、Email
。
执行命令生成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
}
code
为0
代表成功,去数据库查看是否插入了一条数据:
SELECT * FROM users;
ID | Username | Password | Created_At | Updated_At | |
---|---|---|---|---|---|
1 | oldme | 123456 | tyyn1022@gmail.com | 2024-11-08 10:36:48 | 2024-11-08 10:36:48 |
Created_At
和Updated_At
是两个约定字段,会被ORM
自动维护,分别代表创建时间和修改时间。