gozero 实战 Food Foodlist

2023年 10月 9日 95.1k 0

API Gateway 代码调用 food api 服务

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

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 集合:

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 接口中新增该方法的声明:

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 集合:

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 接口中新增该方法的声明:

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 如下:

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 端口

➜  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 接口:

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

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

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

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

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论