GoFrame学习随便记2

我们继续前一篇,来实现 Lookup 的新增。

API方面 :在 api/lookup/v1/lookup.go 后继续添加API请求结构和响应结构 (请求参数用指针形式,因为指针形式可以避免golang类型默认值的影响,例如整型默认值为0,即指针形式的参数意味着用户可能不传递它),主键整数用 int64,不然 int 会遇到类型转换

Go 复制代码
type IndexReq struct {
	g.Meta   `path:"/lookup/index" method:"get"`
	Id       *int64  `json:"id" dc:"ID"`
	Name     *string `json:"name" dc:"名称"`
	Code     *int    `json:"code" dc:"代码"`
	Type     *string `json:"type" dc:"类别"`
	Position *int    `json:"position" dc:"排序位置"`
}

type IndexRes struct {
	List []*entity.Lookup `json:"list" dc:"条目列表"`
}

type CreateReq struct {
	g.Meta   `path:"/lookup/create" method:"post" sm:"创建" tags:"条目"`
	Name     string `json:"name" v:"required|length:1,100" dc:"名称"`
	Code     int    `json:"code" v:"required|integer" dc:"代码"`
	Type     string `json:"type" v:"required|length:1,100" dc:"类别"`
	Position int    `json:"position" dc:"排序位置"`
}

type CreateRes struct {
	Id int64 `json:"id" dc:"ID"`
}

业务逻辑方面:在 internal/logic/lookup/lookup.go 后面添加代码 (对获取列表的方法进行了重命名Refactor)。业务逻辑要和数据库打交道,主要是通过 dao ORM方式实现。

Go 复制代码
func (s *sLookup) Index(ctx context.Context, in *do.Lookup) (res *v1.IndexRes, err error) {
	res = &v1.IndexRes{}
	err = dao.Lookup.Ctx(ctx).
		OrderAsc(dao.Lookup.Columns().Code).
		OrderAsc(dao.Lookup.Columns().Id).
		Scan(&res.List)
	return
}

func (s *sLookup) Create(ctx context.Context, in *do.Lookup) (res *v1.CreateRes, err error) {
	var cols = dao.Lookup.Columns()
	cnt, err := dao.Lookup.Ctx(ctx).
		Where(cols.Code, in.Code).
		Where(cols.Type, in.Type).Count()
	if err != nil {
		return nil, err
	}
	if cnt > 0 {
		return nil, gerror.New("该类型此代码的条目已经存在")
	}
	insertId, err := dao.Lookup.Ctx(ctx).Data(in).InsertAndGetId()
	if err != nil {
		return nil, err
	}
	res = &v1.CreateRes{
		Id: insertId,
	}
	return
}

用 gf gen ctrl反向生成抽象接口 (其实只是已经存在的 api/lookup/lookup.go 的 ILookupV1 interface 里面多了个接口方法,表示给控制器方法加了约定)和控制器方法 (生成 internal/controller/lookup/lookup_v1_create.go 文件)。

用 gf gen service 反向生成抽象接口(其实只是已经存在的 internal/service/lookup.go 的 ILookup interface 里面多了个接口方法,表示给业务逻辑方法加了约定)。

最后就是完善控制器方法internal/controller/lookup/lookup_v1_create.go:查找服务对象并调用业务逻辑方法,将用户请求req的数据传入do,处理结果装入响应res。(写用do对象)

Go 复制代码
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
	//return nil, gerror.NewCode(gcode.CodeNotImplemented)
	res, err = service.Lookup().Create(ctx, &do.Lookup{
		Name:     req.Name,
		Code:     req.Code,
		Type:     req.Type,
		Position: req.Position,
	})
	return
}

以上三步走是典型的步骤。我们在 Goland 中来测试一下功能:在 api/lookup 目录点右键,新建 HTTP Request 文件 lookup-crud.http (可以 Tools - Http Client 菜单下的 Collection 子菜单中抄怎么写请求),不通过请求之间空开一行且最后一行保留一个注释行

bash 复制代码
### GET lookup list
GET http://localhost:8000/lookup/index

### POST lookup create
POST http://localhost:8000/lookup/create
Content-Type: application/json

{
  "name": "test-name1",
  "code": {{$random.integer()}},
  "type": "testCategory",
  "position": 0
}

### end

点左边的绿色箭头,可以执行对应的请求。(当然,首先要观察 gf run main.go 的热更新编译结果是正常的)

我们来把更新、查看、删除功能补充完整。

第一步,请求和响应的结构定义,在 api/lookup/v1/lookup.go 中添加

Go 复制代码
type UpdateReq struct {
	g.Meta   `path:"/lookup/update/{id}" method:"post" sm:"更新" tags:"条目"`
	Id       int64   `json:"id" v:"required|integer" dc:"ID"`
	Name     *string `json:"name" v:"length:1,100" dc:"名称"`
	Code     *int    `json:"code" v:"integer" dc:"代码"`
	Type     *string `json:"type" v:"length:1,100" dc:"类别"`
	Position *int    `json:"position" dc:"排序位置"`
}

type UpdateRes struct{}

type DeleteReq struct {
	g.Meta `path:"/lookup/delete/{id}" method:"post" sm:"删除" tags:"条目"`
	Id     int64 `json:"id" v:"required|integer" dc:"ID"`
}

type DeleteRes struct{}

type ViewReq struct {
	g.Meta `path:"/lookup/view/{id}" method:"get" sm:"详情" tags:"条目"`
	Id     int64 `json:"id" v:"required|integer" dc:"ID"`
}

type ViewRes struct {
	*entity.Lookup `dc:"条目"`
}

第二步,编写相应的业务逻辑,在 internal/logic/lookup/lookup.go 下添加

Go 复制代码
func (s *sLookup) Update(ctx context.Context, in *do.Lookup) (res *v1.UpdateRes, err error) {
	_, err = dao.Lookup.Ctx(ctx).Data(in).WherePri(in.Id).Update()
	return
}

func (s *sLookup) Delete(ctx context.Context, id int64) (res *v1.DeleteRes, err error) {
	_, err = dao.Lookup.Ctx(ctx).WherePri(id).Delete()
	return
}

func (s *sLookup) View(ctx context.Context, id int64) (res *v1.ViewRes, err error) {
	res = &v1.ViewRes{}
	err = dao.Lookup.Ctx(ctx).WherePri(id).Scan(&res.Lookup)
	return
}

第三步,生成代码并完善控制器,先 gf gen ctrl 生成控制器方法文件,再 gf gen service 生成(其实是修改)服务接口文件。更新方法 internal/controller/lookup/lookup_v1_update.go 修改为

Go 复制代码
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
	//return nil, gerror.NewCode(gcode.CodeNotImplemented)
	res, err = service.Lookup().Update(ctx, &do.Lookup{
		Id:       req.Id,
		Name:     req.Name,
		Code:     req.Code,
		Type:     req.Type,
		Position: req.Position,
	})
	return
}

查看方法 internal/controller/lookup/lookup_v1_view.go 修改为

Go 复制代码
func (c *ControllerV1) View(ctx context.Context, req *v1.ViewReq) (res *v1.ViewRes, err error) {
	//return nil, gerror.NewCode(gcode.CodeNotImplemented)
	res, err = service.Lookup().View(ctx, req.Id)
	return
}

删除方法 internal/controller/lookup/lookup_v1_delete.go 修改为

Go 复制代码
func (c *ControllerV1) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) {
	//return nil, gerror.NewCode(gcode.CodeNotImplemented)
	res, err = service.Lookup().Delete(ctx, req.Id)
	return
}

请求测试文件 api/lookup/lookup-crud.http 添加

bash 复制代码
### POST lookup update
POST http://localhost:8000/lookup/update/6
Content-Type: application/json

{
  "name": "test-name3",
  "code": 478,
  "type": "testCategory",
  "position": 1
}

### GET lookup view
GET http://localhost:8000/lookup/view/6
Content-Type: application/json

{
  "id": 6
}

### POST lookup delete
POST localhost:8000/lookup/delete/6
Content-Type: application/json

测试一下,可以发现总体上已经实现了 CRUD 功能。但似乎存在一点小问题,对于 update、view、delete,如果对应 id 的记录不存在,也会返回成功,只是没有对应记录。index 还没有测试加筛选条件的情况。

相关推荐
律宏阔2 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔2 小时前
Windows 禁用联想笔记本所有 Lenovo 后台服务
windows
律宏阔2 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
一隅论数智6 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
小羊没烦恼!6 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
rockmelodies6 天前
# Windows Server2008 R2 Standard(SP1镜像U盘)重置本地管理员密码【完整详细步骤】
windows·密码破解
XiHongShi20166 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
爱吃苹果的日记本6 天前
离散数学第六课
学习·离散数学
AI职业加油站6 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展