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

相关推荐
2301_765715142 小时前
深入操作系统核心:全面解析存储管理机制
windows
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ2 小时前
List、Set的相似性
windows·tomcat·list
qq_344115222 小时前
WinForm学习笔记一(建立项目)
笔记·学习
小呀小萝卜儿2 小时前
2026-01-14 学习记录--LLM-申请Hugging Face 访问令牌(以Meta-Llama-3.1-8B-Instruct为例)
学习·语言模型·llama
走在路上的菜鸟2 小时前
Android学Flutter学习笔记 第五节 Android视角认知Flutter(插件plugins)
android·学习·flutter
2301_800256112 小时前
【人工智能引论期末复习】第4章 机器学习3-无监督学习
人工智能·学习·机器学习
星火开发设计2 小时前
深入浅出HDFS:分布式文件系统核心原理与实践解析
大数据·数据库·hadoop·学习·hdfs·分布式数据库·知识
刘孬孬沉迷学习2 小时前
6G 六大应用场景
学习·5g·信息与通信·6g·5g nr·6g 应用场景
修炼室2 小时前
在 Windows 上构建不占 C 盘的科研级 WSL 实验环境(Ubuntu 22.04)
c语言·windows·ubuntu