我们通过一个系列文章跟大家详细展示一个 go-zero
微服务实例,整个系列分十三篇文章,目录结构如下:
- go-zero 实战 - 服务划分与项目创建
- go-zero 实战 - User API Gateway
- go-zero 实战 - User Login
- go-zero 实战 - User Register
- go-zero 实战 - User Userinfo
- go-zero 实战 - Food API Gateway
- go-zero 实战 - Food Search
- go-zero 实战 - Food AddFood
- go-zero 实战 - Food DeleteFood
- go-zero 实战 - Food Foodlist
- go-zero 实战进阶 - rpc 服务
- go-zero 实战进阶 - 用户管理 rpc 服务
- go-zero 实战进阶 - 食材管理 rpc 服务
期望通过本系列文章带你在本地利用 go-zero
快速开发一个《食谱指南》系统,让你快速上手微服务。
本篇我们将讲解如何创建 食材搜索
接口。同样的,你将在本篇学习到以下内容:
- 创建
food
表,并定义数据库表结构,以便保存食材信息; - 利用 goctl model 命令,生成
mysql CRUD
代码; - 完善搜索接口逻辑内容。
创建 food
表,并定义数据库表结构
在本机 mysql
中的 foodguides
数据库中,执行如下 SQL
语句新建 food
表:
CREATE TABLE `food` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '食物Id',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物名称',
`protein` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物蛋白质含量',
`fat` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物脂肪含量',
`carbohydrate` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物碳水化合物含量',
`calorie` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物卡路里',
`minerals` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物矿物质含量',
`calcium` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物钙含量',
`phosphorus` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物磷含量',
`iron` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物铁含量',
`purine` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '食物嘌呤含量',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `name_index` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
接下来,我们执行以下 SQL
语句,新增一条食材数据,为搜索结果做准备:
INSERT INTO `foodguides`.`food`(`id`, `name`, `protein`, `fat`, `carbohydrate`, `calorie`, `minerals`, `calcium`, `phosphorus`, `iron`, `purine`, `create_time`, `update_time`) VALUES (1, '鱿鱼', '60.0', '4.6', '7.8', '1323', '100', '87', '392', '4.1', '100', '2021-01-26 23:30:43', '2021-01-26 23:33:38');
执行 goctl model
命令,生成 mysql CRUD
代码
在 foodmanage/model
目录下新建 food.sql
文件,并将上述创建 food
数据库表的 SQL
语句复制到该文件中。
cd
到 foodmanage/model
目录下,执行 goctl model
命令生成 mysql CRUD
代码:
$ goctl model mysql ddl -src food.sql -dir .
Done.
查看 model
目录结构
➜ model:
$ tree
.
├── food.sql
├── foodmodel.go
├── foodmodel_gen.go
└── vars.go
修改 food.yaml
配置文件
$ vim foodmanage/api/food/etc/food.yaml
Name: food-api
Host: 0.0.0.0
Port: 8889
Mysql:
DataSource: root:123456@tcp(127.0.0.1:9528)/foodguides?charset=utf8mb4&parseTime=True&loc=Local
Auth:
AccessSecret: ad879037-d3fd-tghj-112d-6bfc35d54b7d
AccessExpire: 86400
添加服务配置
$ vim foodmanage/api/internal/config/config.go
package config
import "github.com/zeromicro/go-zero/rest"
type Config struct {
rest.RestConf
Mysql struct {
DataSource string
}
Auth struct {
AccessSecret string
AccessExpire int64
}
}
注册服务上下文的依赖
$ vim foodmanage/api/internal/svc/serviceContext.go
package svc
import (
"FoodGuides/service/foodmanage/api/internal/config"
"FoodGuides/service/foodmanage/model"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type ServiceContext struct {
Config config.Config
FoodModel model.FoodModel
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
FoodModel: model.NewFoodModel(sqlx.NewMysql(c.Mysql.DataSource)),
}
}
添加搜索接口逻辑
$ vim foodmanage/api/internal/logic/searchlogic.go
package logic
import (
"context"
"strconv"
"FoodGuides/service/foodmanage/api/internal/svc"
"FoodGuides/service/foodmanage/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type SearchLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewSearchLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SearchLogic {
return &SearchLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *SearchLogic) Search(req *types.SearchRequest) (*types.SearchResponse, error) {
searchKey := req.Key
food, err := l.svcCtx.FoodModel.FindOneByName(l.ctx, searchKey)
if err != nil {
return nil, err
}
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,
}
return &types.SearchResponse{FoodReply: foodReply}, nil
}
修改 Response
返回格式
$ vim foodmanage/api/internal/handler/searchhandler.go
package handler
import (
"FoodGuides/common/responsex"
"net/http"
"FoodGuides/service/foodmanage/api/internal/logic"
"FoodGuides/service/foodmanage/api/internal/svc"
"FoodGuides/service/foodmanage/api/internal/types"
"github.com/zeromicro/go-zero/rest/httpx"
)
func SearchHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.SearchRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.OkJson(w, responsex.FailureResponse(nil, err.Error(), 1000))
return
}
l := logic.NewSearchLogic(r.Context(), svcCtx)
resp, err := l.Search(&req)
if err != nil {
httpx.OkJson(w, responsex.FailureResponse(nil, err.Error(), 1000))
} else {
httpx.OkJson(w, responsex.SuccessResponse(resp, "搜索成功"))
}
}
}
启动服务
启动 food api
服务, 运行成功后,food api
则运行在本机的 8889
端口
➜ service:
$ go run foodmanage/api/food.go -f foodmanage/api/etc/food-api.yaml
Starting server at 0.0.0.0:8889...
我们用 Postman
尝试请求搜索接口,有如下截图的响应说明搜索服务运行正常。
至此,Food Search
Api 就开发完了。下一篇将介绍如何搭建添加食材的接口。