准备好数据模型后,就可以使用我们的"三板斧"法则开发用户接口了。
添加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调用从而实现具体的业务逻辑。
定义一个Users对象,并新建一个New函数用作实例化它:
internal/logic/users/users.go
package users
type Users struct {
}
func New() *Users {
return &Users{}
}
编写注册方法:
internal/logic/users/users_register.go
package users
import (
"context"
"star/internal/dao"
"star/internal/model/do"
)
func (u *Users) 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即可。
将Users对象封装到控制器中,方便后续调用。
internal/controller/users/users_new.go
...
package users
import (
"star/api/users"
userLogic "star/internal/logic/users"
)
type ControllerV1 struct {
users *userLogic.Users
}
func NewV1() users.IUsersV1 {
return &ControllerV1{
users: userLogic.New(),
}
}
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 = c.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自动维护,分别代表创建时间和修改时间。