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 还没有测试加筛选条件的情况。

相关推荐
YCY^v^30 分钟前
JeecgBoot 项目运行指南
java·学习
云小逸36 分钟前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
JustDI-CM1 小时前
AI学习笔记-提示词工程
人工智能·笔记·学习
春日见1 小时前
如何创建一个PR
运维·开发语言·windows·git·docker·容器
悟纤1 小时前
学习与专注音乐流派 (Study & Focus Music):AI 音乐创作终极指南 | Suno高级篇 | 第33篇
大数据·人工智能·深度学习·学习·suno·suno api
爱写bug的野原新之助1 小时前
加密摘要算法MD5、SHA、HMAC:学习笔记
笔记·学习
C++ 老炮儿的技术栈1 小时前
VS2015 + Qt 实现图形化Hello World(详细步骤)
c语言·开发语言·c++·windows·qt
ZH15455891312 小时前
Flutter for OpenHarmony Python学习助手实战:Web开发框架应用的实现
python·学习·flutter
百锦再2 小时前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
浩浩测试一下2 小时前
内网---> WriteOwner权限滥用
网络·汇编·windows·安全·microsoft·系统安全