wordpress站群搭建5api和rpc业务代码编写

wordpress站群搭建5api和rpc业务代码编写

本次目标我们主要讲解怎么编写业务代码。

由于我们大部门接口代码已经自动生成了,我们就只需要编写业务代码即可。

这里我们以编写查询posts 的接口为例子。

1.启动swagger

我们启动swagger方便我们随时进行测试。

 swagger serve --no-open -F=swagger --port 36666 station.json

在这里插入图片描述

2.编写api代码

进入api\internal\logic目录,我们编写查询接口,大致会有如下几个步骤:

1.转换查询条件 2.调用rpc接口查询 3.转换返回结果

querypostslogic.go

func (l *QueryPostsLogic) QueryPosts(req *types.PostsReq) (resp *types.PostsListResp, err error) {
	// 1.转换查询struct
	rpcRep := &station.PostsReq{
		PageInfo: &station.PageInfo{
			Page:     req.Page,
			PageSize: req.PageSize,
		},
		Title:      req.Title,
		Source:     req.Source,
		Author:     req.Author,
		Categories: req.Categories,
	}
	if req.CreateTime > 0 {
		rpcRep.CreateTime = time.UnixMilli(req.CreateTime).Format("2006-01-02")
	}
	// 2调用rpc接口查询
	postsListInfo, err := l.svcCtx.PostsRpc.QueryPosts(l.ctx, rpcRep)
	if err != nil {
		return nil, err
	}
	// 3.转换结果
	resp = &types.PostsListResp{
		BaseDataInfo: types.BaseDataInfo{
			Code:    0,
			Message: "success",
		},
		Data: types.PostsListInfo{
			BaseListInfo: types.BaseListInfo{
				Total: postsListInfo.BaseListInfo.Total,
			},
		},
	}
	for _, item := range postsListInfo.Data {
		resp.Data.Data = append(resp.Data.Data, types.PostsInfo{
			Id:         item.Id,
			Title:      item.Title,
			Source:     item.Source,
			Author:     item.Author,
			ThrownNum:  item.ThrownNum,
			Categories: item.Categories,
			CreateTime: item.CreateTime,
			Content:    item.Content,
		})
	}
	return resp, nil
}

3.编写rpc代码

进入rpc\internal\logic,同样也是类似3个步骤

1.转换查询条件 2.调用model接口查询 3.转换返回结果

调用model接口这里是复杂查询,我们需要自己进行数据库逻辑编写,这里我们先定义出model接口

QueryPosts(ctx context.Context,in *station.PostsReq )([]*Posts,uint64,error)

querypostslogic.go

func (l *QueryPostsLogic) QueryPosts(in *station.PostsReq) (*station.PostsListInfo, error) {
	// 1.转换擦查询体条件
	// 2.查询数据库
	list, total, err := l.svcCtx.PostsModel.QueryPosts(l.ctx, in)
	if err != nil {
		return nil, err
	}
	// 3.转换返回数据
	resp := &station.PostsListInfo{
		BaseListInfo: &station.BaseListInfo{
			Total: total,
		},
	}
	if total > 0 {
		for _, item := range list {
			resp.Data = append(resp.Data, &station.PostsInfo{
				Id:         item.Id,
				Title:      item.Title.String,
				Source:     item.Source.String,
				Author:     item.Author.Int64,
				ThrownNum:  item.ThrownNum.Int64,
                CreateTime: item.CreateAt.UnixMilli(),
				Categories: item.Categories.String,
			})
		}
	}
	return resp, nil
}

3.数据库逻辑代码

上面我们只是定义出QueryPosts 数据库查询接口,接下来我们编写具体的数据库查询代码

进入rpc\model 目录

postsmodel_gen.go

// 定义接口
postsModel interface {
    Insert(ctx context.Context, data *Posts) (sql.Result, error)
    FindOne(ctx context.Context, id uint64) (*Posts, error)
    QueryPosts(ctx context.Context,in *station.PostsReq )([]*Posts,uint64,error)
    Update(ctx context.Context, data *Posts) error
    Delete(ctx context.Context, id uint64) error
}
// 编写查询逻辑
func (m *defaultPostsModel) QueryPosts(ctx context.Context,data *station.PostsReq )([]*Posts,uint64,error){
	//构建查询条件
	query := "where 1=1"
	params :=make([]interface{},0,0)
	if data.Title!=""{ 
		query += " and title like ?"
		params = append(params,  "%"+data.Title+"%")
	}
	if data.Source!=""{ 
		query += " and source = ?"
		params = append(params,  data.Source)
	}
	if data.Author!=0{ 
		query += " and author = ?"
		params = append(params,  data.Author)
	}
	if data.Categories!=""{ 
		query += " and categories = ?"
		params = append(params,  data.Categories)
	}
	if data.CreateTime!=""{ 
		query += " and create_time >= ? and create_time < ?"
		params = append(params,  fmt.Sprintf("%v 00:00:00",data.CreateTime))
		params = append(params,  fmt.Sprintf("%v 23:59:59:999",data.CreateTime))
	}
	//查数量
	total := 0
	items := make([]*Posts, 0)
	err := m.conn.QueryRow(&total,fmt.Sprintf("select count(1) from %s ", m.table) + query, params...)
	if err!=nil {
		return nil,0, err
	}
	// 没有记录
	if total == 0 {
		return items, uint64(total), nil
	}
	//分页
	query += "  order by id desc LIMIT ? OFFSET ?"
	params = append(params, data.PageInfo.PageSize)
	params = append(params, data.PageInfo.PageSize*(data.PageInfo.Page-1))
	err = m.conn.QueryRows(&items, fmt.Sprintf("select %s from %s", postsRows, m.table) + query, params...)
	if err!=nil {
		return nil,0, err
	}
	return items,uint64(total),nil
}

4.测试

上面就是一个简单的查询接口编写流程,我们测试下

进入rpc目录,启动rpc

go run station.go

进入api目录,启动api

go run staion.go

进入swagger调用接口进行测试

http://127.0.0.1:8000/station/api/posts?page=1&pageSize=2&createTime=1721639216052

返货ok
{
  "code": 0,
  "message": "success",
  "data": {
    "total": 1,
    "data": [
      {
        "id": 1,
        "title": "1",
        "source": "1",
        "author": 1,
        "thrownNum": 1,
        "categories": "1",
        "createTime": 1721639216052,
        "content": ""
      }
    ]
  }
}

根据接口响应我们对接口进行逻辑调整。

如果是实体和接口需要调整我们可以修改 .api文件 和 .proto文件进行调整。然后使用脚手架命令重新生成。

5.总结

上面就是一个分布式接口的一般开发流程。基于go-zore我们的业务代码写在logic包中,一般来说只需要关注logic和model。

当然这里的model可以使用orm框架进行替代,如gorm,ent。可以根据自己的需要进行替换。

如果是单体项目那就没有rpc这个环节,api直接和model交互。

具体完整的api代码可以查看源码

6.tips

事务有必要讲下,我们以新增文章为例,文章分为posts和posts_text表,我们需要同时新增成功,这时候就需要用到事务。

下面是使用事务的例子

// 新增Posts 和PostsText
func (m *defaultPostsModel) AddPosts(ctx context.Context, data *Posts, text *PostsText) (int64,error){
	var id int64
    // 开启事务
	err := m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
        query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, postsRowsExpectAutoSet)
		r, err := session.ExecCtx(ctx, query, data.Title, data.Source, data.Author, data.ThrownNum, data.Categories,data.Creater,data.Modifier)
        if err != nil {
            return err
        }
		id ,err = r.LastInsertId()
		if err != nil {
            return err
        }
		query = fmt.Sprintf("insert into %s (%s) values (?, ?)", "posts_text", postsTextRowsExpectAutoSet)
        _ ,err =session.ExecCtx(ctx, query, id , text.Content)
        if err != nil {
            return err
        }
		return nil
    })
	if err!=nil {
		return id,err
	}
	return id,nil
}

完整代码查看5api和rpc业务代码编写 分支

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值