go-zero 实战 - Food Foodlist

API Gateway 代码调用 food api 服务

编辑 api/internal/handler 下的 foodlisthandler.go 文件,修改 FoodListHandler 方法如下:

go 复制代码
func FoodListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
       l := logic.NewFoodListLogic(r.Context(), svcCtx)
       resp, err := l.FoodList()
       if err != nil {
          httpx.OkJson(w, renpanpan.FailureResponse(nil, err.Error(), 1000))
       } else {
          httpx.OkJson(w, renpanpan.SuccessResponse(resp, "请求成功"))
       }
    }
}

因为 /food/foodlist 需要返回指定用户下的所有食物信息,因此需要先根据 userId 从 user_food 表中查询所有匹配到记录的 foodid 集合,再利用 foodid 集合从 food 表中查询到所有匹配到的 food 集合。

编辑 model 下的 userfoodmodel_gen.go 文件,添加方法 FindManyByUserid,表示根据 userId 从 user_food 表中查询所有匹配到记录的 UserFood 集合:

go 复制代码
func (m *defaultUserFoodModel) FindManyByUserid(ctx context.Context, userid int64) ([]*UserFood, error) {
    var resp []*UserFood
    query := fmt.Sprintf("select %s from %s where `userid` = ?", userFoodRows, m.table)
    err := m.conn.QueryRowsCtx(ctx, &resp, query, userid)
    switch err {
    case nil:
       return resp, nil
    case sqlc.ErrNotFound:
       return nil, ErrNotFound
    default:
       return nil, err
    }
}

同时在 userfoodmodel_gen.go 文件的 userFoodModel 接口中新增该方法的声明:

go 复制代码
type (
    userFoodModel interface {
       Insert(ctx context.Context, data *UserFood) (sql.Result, error)
       FindOne(ctx context.Context, id int64) (*UserFood, error)
       FindOneByUserid(ctx context.Context, userid int64) (*UserFood, error)
       FindManyByUserid(ctx context.Context, userid int64) ([]*UserFood, error) // 新增方法声明
       Update(ctx context.Context, data *UserFood) error
       Delete(ctx context.Context, id int64) error
    }

    defaultUserFoodModel struct {
       conn  sqlx.SqlConn
       table string
    }

    UserFood struct {
       Id         int64     `db:"id"`     // id
       Userid     int64     `db:"userid"` // 用户Id
       Foodid     int64     `db:"foodid"` // 食物Id
       CreateTime time.Time `db:"create_time"`
       UpdateTime time.Time `db:"update_time"`
    }
)

编辑 model 下的 foodmodel_gen.go 文件,添加方法 FindMany,表示根据 foodid 集合从 food 表中查询到所有匹配到的 food 集合:

go 复制代码
func (m *defaultFoodModel) FindMany(ctx context.Context, ids []string) ([]*Food, error) {
    query := fmt.Sprintf("select %s from %s where `id` in (%s)", foodRows, m.table, strings.Join(ids, ","))
    var resp []*Food
    err := m.conn.QueryRows(&resp, query)
    switch err {
    case nil:
       return resp, nil
    case sqlc.ErrNotFound:
       return nil, ErrNotFound
    default:
       return nil, err
    }
}

同样在 foodmodel_gen.go 文件的 foodModel 接口中新增该方法的声明:

go 复制代码
type (
    foodModel interface {
       Insert(ctx context.Context, data *Food) (sql.Result, error)
       FindOne(ctx context.Context, id int64) (*Food, error)
       FindMany(ctx context.Context, ids []string) ([]*Food, error) // 新增方法声明
       FindOneByName(ctx context.Context, name string) (*Food, error)
       Update(ctx context.Context, data *Food) error
       Delete(ctx context.Context, id int64) error
    }

    defaultFoodModel struct {
       conn  sqlx.SqlConn
       table string
    }

    Food struct {
       Id           int64     `db:"id"`           // 食物Id
       Name         string    `db:"name"`         // 食物名称
       Protein      string    `db:"protein"`      // 食物蛋白质含量
       Fat          string    `db:"fat"`          // 食物脂肪含量
       Carbohydrate string    `db:"carbohydrate"` // 食物碳水化合物含量
       Calorie      string    `db:"calorie"`      // 食物卡路里
       Minerals     string    `db:"minerals"`     // 食物矿物质含量
       Calcium      string    `db:"calcium"`      // 食物钙含量
       Phosphorus   string    `db:"phosphorus"`   // 食物磷含量
       Iron         string    `db:"iron"`         // 食物铁含量
       Purine       string    `db:"purine"`       // 食物嘌呤含量
       CreateTime   time.Time `db:"create_time"`
       UpdateTime   time.Time `db:"update_time"`
    }
)

至此,我们已经准备好数据来源的查询方法,编辑 api/internal/logic 下的 foodlistlogic.go 文件,修改方法 FoodList 如下:

go 复制代码
func (l *FoodListLogic) FoodList() (*types.FoodResponse, error) {
    
    userId, _ := l.ctx.Value("userId").(json.Number).Int64()
    userFoods, err := l.svcCtx.UserFood.FindManyByUserid(l.ctx, userId)
    if err != nil {
       return nil, err
    }
    
    var foodIds []string
    for _, food := range userFoods {
       foodIds = append(foodIds, strconv.FormatInt(food.Foodid, 10))
    }
    foods, err1 := l.svcCtx.Food.FindMany(l.ctx, foodIds)
    if err1 != nil {
       return nil, err1
    }

    var foodReplys []types.FoodReply

    for _, food := range foods {
       foodReply := types.FoodReply{
          Id:           strconv.FormatInt(food.Id, 10),
          Name:         food.Name,
          Protein:      food.Protein,
          Fat:          food.Fat,
          Carbohydrate: food.Carbohydrate,
          Calorie:      food.Calorie,
          Minerals:     food.Minerals,
          Calcium:      food.Calcium,
          Phosphorus:   food.Phosphorus,
          Iron:         food.Iron,
          Purine:       food.Purine,
       }
       foodReplys = append(foodReplys, foodReply)
    }

    return &types.FoodResponse{List: foodReplys}, nil
}

启动服务

启动 food api 服务, 运行成功后,food api 则运行在本机的 8889 端口

bash 复制代码
➜  FoodGuides: 
$ go run foodmanage/api/food.go -f foodmanage/api/etc/food-api.yaml
Starting server at 0.0.0.0:8889...

我们用 Postman 尝试请求 /food/foodlist 接口:

  1. 在 Postman 的 Authorization 选项中选择 Bearer Token,填写登录成功后 Api 返回的 accessToken 字段值。
  2. 点击发送请求按钮,有如下截图的响应说明接口运行正常。

这样 Food - Foodlist 就开发完成了。

上一篇《go-zero 实战 - Food DeleteFood》

首篇《go-zero 实战 - 服务划分与项目创建》

相关推荐
FungLeo4 小时前
成为全栈·Go 后端篇·契约一致性与差分测试:两套实现如何互相校验
golang·node.js·go·合约测试·差分测试·成为全栈·api兼容
vipxieliang8 小时前
Go 1.25 Green Tea GC 深度解析:以页为单位的垃圾回收新范式
go
孔令飞8 小时前
AI 时代岗位调研分析:调研了近3000份AI岗位描述,分享下调研结果
云原生·go·ai编程
我不会起名字3229 小时前
Redis 从 0 到 1(十二):先删缓存还是先更新库?4 种方案的 Go 并发实测
redis·go·并发·延迟双删·缓存一致性
FungLeo1 天前
成为全栈·Go 后端篇·用 Go 重写分层架构:领域包、装配根与最小抽象
golang·go·领域驱动设计·gorm·分层架构·成为全栈
我不会起名字3221 天前
Go 服务升级 Go 1.2x 后 P99 变差:GMP 调度相关的 3 个变化
golang·go·gmp·调度·gomaxprocs
孔令飞2 天前
知己知彼,百战不殆:AI SKILL 实现原理剖析
云原生·go·ai编程
孔令飞3 天前
工具分享:OneX AI 工具安装、配置及功能介绍
云原生·go·ai编程
喵了几个咪3 天前
GoWind Admin 拆解:一个 Sender 接口接 39 个通知渠道
微服务·golang·go·1024程序员节·admin·gowind
l1t3 天前
在windows中测试musql数据库
数据库·sqlite·go·1024程序员节