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 需要返回指定用户下的所有食物信息,因此需要先根据 userIduser_food 表中查询所有匹配到记录的 foodid 集合,再利用 foodid 集合从 food 表中查询到所有匹配到的 food 集合。

编辑 model 下的 userfoodmodel_gen.go 文件,添加方法 FindManyByUserid,表示根据 userIduser_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. PostmanAuthorization 选项中选择 Bearer Token,填写登录成功后 Api 返回的 accessToken 字段值。
  2. 点击发送请求按钮,有如下截图的响应说明接口运行正常。

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

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

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

相关推荐
岁忧36 分钟前
(LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)
java·c++·算法·leetcode·面试·go
Nejosi_念旧1 小时前
解读 Go 中的 constraints包
后端·golang·go
漫步向前8 小时前
gin问题知识点汇总
go
mao毛8 小时前
go Mutex 深入理解
go·源码阅读
钩子波比10 小时前
🚀 Asynq 学习文档
redis·消息队列·go
漫步向前12 小时前
beegoMVC问题知识点汇总
go
一个热爱生活的普通人16 小时前
Go 泛型终极指南:告别 interface{},写出更安全、更强大的代码!
后端·go
DemonAvenger18 小时前
实现可靠的 UDP 协议:Go 语言版本
网络协议·架构·go
程序员爱钓鱼1 天前
Go语言实战案例-读取用户输入并打印
后端·google·go
{⌐■_■}1 天前
【Kafka】登录日志处理的三次阶梯式优化实践:从同步写入到Kafka多分区批处理
数据库·分布式·mysql·kafka·go