写点什么

Go-Zero 从 0 到 1 实现微服务项目开发(二)

作者:王中阳Go
  • 2024-04-29
    北京
  • 本文字数:5895 字

    阅读完需:约 19 分钟

Go-Zero从0到1实现微服务项目开发(二)

前言

书接上回,继续更新 GoZero 微服务实战系列文章。


上一篇被 GoZero 作者万总点赞了,更文动力倍增,也建议大家先看巧一篇,欢迎粉丝股东们三连支持一波:Go-zero微服务快速入门和最佳实践(一)



本文将继续使用 Go-zero 提供的工具和组件,从零开始逐步构建一个基本的微服务项目。手把手带你完成:项目初始化+需求分析+表结构设计+api+rpc+goctl+apifox 调试+细节处理。带你实现一个完整微服务的开发。

实战前准备

首先需要你在本地安装 goctl、protoc、go-zero,goctl安装,按照教程操作即可,非常简单。


下面按顺序和我操作吧,对整体开发流程不清楚的同学务必先看我上一篇文章:GoZero的开发技巧 & 整体开发流程

实战开始

1 | 新建项目(本文使用 GoLand)

左上角 File-->选择 New-->点击 Project(如果是第一次使用直接点击 New Project 即可)



选择新建项目的文件夹以及命名,选择 Go 的版本(我使用的是 Go 1.22.1)



新建文件目录如下


2 | 设计库和表,生成 model(本文以文章 article 表举例,带你实现增删改查基础功能)

数据库表结构设计



快速定位到 model 目录下执行该命令(右键 model-->找到 Open In-->点击 Terminal)



使用 goctl 命令生成 model(username、passwd、host、port、dbname、tables 换成自己的对应的数据)


goctl model mysql datasource -url="${username}:${passwd}@tcp(${host}:${port})/${dbname}" -table="${tables}" -dir="./" -cache=true --style=goZero
复制代码


一键生成:


3 | 设计 api 层

在 api 目录下新建文件:



在 article.api 中定义文章服务的请求和响应


syntax = "v1"
info ( title: "文章服务" desc: "文章服务" version: "v1")
// 数据库中对应的article表type Article { Id int64 `json:"id"` Title string `json:"title"` Content string `json:"content"`}//---------------------------Req&Resp------------------------------// 获取文章列表type ( GetArticleListReq { }
GetArticleListResp { Articles []Article `json:"Articles"` })// 创建文章type ( CreateArticleReq { Title string `json:"title"` Content string `json:"content"` } CreateArticleResp { })// 删除文章type ( DeleteArticleReq { Id int64 `json:"id"` } DeleteArticleResp { })// 修改文章type ( UpdateArticleReq { Id int64 `json:"id"` Title string `json:"title"` Content string `json:"content"` } UpdateArticleResp { })
复制代码


在 main.api 中定义文章服务的 API


syntax = "v1"
info ( title: "文章服务" desc: "文章服务" version: "v1")
// 导入article.api,直接引用import ( "article/article.api")
// 服务的相关配置,这里分别是前缀和分组@server ( prefix: article/v1 group: article)service article { @doc "获得文章列表" @handler getArticles post /getArticles (GetArticleListReq) returns (GetArticleListResp)
@doc "创建文章" @handler createArticle post /createArticle (CreateArticleReq) returns (CreateArticleResp)
@doc "删除文章" @handler deleteArticle post /deleteArticle (DeleteArticleReq) returns (DeleteArticleResp)
@doc "修改文章" @handler updateArticle post /updateArticle (UpdateArticleReq) returns (UpdateArticleResp)}
复制代码


至此 api 层已经定义好了,接下来使用 goctl 代码自动生成


和刚刚一样,右键 main.api 然后打开 Terminal,输入代码


goctl api go -api main.api -dir ../ --style=goZero 
复制代码


会自动生成 etc、internal 文件夹以及 article.go 文件(我习惯把 article.go 文件改成 main.go 文件:如果我们后续有多个微服务,执行 goctl 命令的时候就不用频繁切换文件名称了)


在这里只需要在意几个配置文件(article.yaml, config.go, serviceContext.go)以及需要编写代码的 logic 目录即可, 暂时先不管, 将 rpc 层也生成好后一起配置。

4 | 编写 rpc 层

在 rpc 下新建 pb 文件夹, 在 pb 文件夹里新建 article.proto 文件


在编写 proto 文件的时候, 如果是第一次编写的话, 可以使用 sql2pb 工具自动生成, 一旦我们的 proto 文件有自定义的修改之后, 就不建议使用这个工具了, 使用方法如下


  1. 安装最新的 sql2pb


go install github.com/Mikaelemmmm/sql2pb@latest
复制代码


  1. 命令示例:


sql2pb -go_package ./pb -host localhost -package pb -password lps123456 -port 3306 -schema zero-demo -service_name article -user root > article.proto
复制代码


这个命令可以直接将我的 zero-demo 数据库下所有的表内容都生成到 article.proto 文件中这是自动生成的 article.proto 文件, ** 你也可以根据自己的需求往里面增加内容**


syntax = "proto3";
option go_package ="./pb";
package pb;
// ------------------------------------ // Messages// ------------------------------------
//--------------------------------article--------------------------------message Article { int64 id = 1; //id string title = 2; //title string content = 3; //content}
message AddArticleReq { string title = 1; //title string content = 2; //content}
message AddArticleResp {}
message UpdateArticleReq { int64 id = 1; //id string title = 2; //title string content = 3; //content}
message UpdateArticleResp {}
message DelArticleReq { int64 id = 1; //id}
message DelArticleResp {}
message GetArticleByIdReq { int64 id = 1; //id}
message GetArticleByIdResp { Article article = 1; //article}
message SearchArticleReq { int64 page = 1; //page int64 limit = 2; //limit int64 id = 3; //id string title = 4; //title string content = 5; //content}
message SearchArticleResp { repeated Article article = 1; //article}


// ------------------------------------ // Rpc Func// ------------------------------------
service article{
//-----------------------article----------------------- rpc AddArticle(AddArticleReq) returns (AddArticleResp); rpc UpdateArticle(UpdateArticleReq) returns (UpdateArticleResp); rpc DelArticle(DelArticleReq) returns (DelArticleResp); rpc GetArticleById(GetArticleByIdReq) returns (GetArticleByIdResp); rpc SearchArticle(SearchArticleReq) returns (SearchArticleResp);
}
复制代码


下一步就是通过 proto 文件自动生成 rpc 层其他代码


和之前说的一样,右键 article.proto 然后打开 Terminal,输入代码:


goctl rpc protoc article.proto --go_out=../ --go-grpc_out=../ --zrpc_out=../ --style=goZero
复制代码


注意: 如果你是 Windows 电脑,运行后可能会出现一个 invalid UTF-8 encoding 的问题, 将左下角的文件格式改为 UTF-8 即可。(更建议你按照 git bash,从根本上解决这个问题。)



运行成功后又会生成好几个文件



这里我同样将 article.go 改成了 main.go

5 | 配置 api 层和 rpc 层

OK,现在没有能自动生成的代码了, 需要自己手动敲代码实现业务逻辑了。

配置 api 层

打开 api/etc/article.yaml 文件, 写入以下代码:


Name: article-api #服务名称Host: 127.0.0.1 #监听地址Port: 1001 #监听端口Mode: dev #运行模式# 配置MySQL RedisDB:  DataSource: root:lps123456@tcp(127.0.0.1:3306)/zero-demo?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghaiCache:  - Host: 127.0.0.1:6379    Pass:# 配置rpc客户端, 后面需要调用rpc中的方法ArticleRpcConf:  Endpoints:    - 127.0.0.1:2001  NonBlock: true
复制代码


接下来是 api/internal/config/config.go 文件


package config
import ( "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/zrpc")type Config struct { rest.RestConf DB struct { DataSource string } Cache cache.CacheConf ArticleRpcConf zrpc.RpcClientConf}
复制代码


最后是 api/internal/svc/serviceContext.go 文件


package svc
import ( "GoZeroDemo/app/article/cmd/api/internal/config" "GoZeroDemo/app/article/cmd/rpc/article" "github.com/zeromicro/go-zero/zrpc")
type ServiceContext struct { Config config.Config ArticleRpc article.ArticleZrpcClient}
func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ Config: c, ArticleRpc: article.NewArticleZrpcClient(zrpc.MustNewClient(c.ArticleRpcConf)), }}
复制代码


api 层的服务就配置好了

配置 rpc 层

打开 rpc/etc/article.yaml 文件, 写入以下代码:


Name: article-rpc #服务名称ListenOn: 127.0.0.1:2001 #监听地址Mode: dev #运行模式# 配置RedisRedis:  Host: 127.0.0.1:6379  Type: node  Pass:  Key: article-rpc# 配置MySQLDB:  DataSource: root:lps123456@tcp(127.0.0.1:3306)/zero-demo?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghaiCache:  - Host: 127.0.0.1:6379    Pass:
复制代码


接下来是 rpc/internal/config/config.go 文件


package config
import ( "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/zrpc")
type Config struct { zrpc.RpcServerConf DB struct { DataSource string } Cache cache.CacheConf}
复制代码


最后是 rpc/internal/svc/serviceContext.go 文件


package svc
import ( "GoZeroDemo/app/article/cmd/rpc/internal/config" "GoZeroDemo/app/article/model" "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/sqlx")
type ServiceContext struct { Config config.Config RedisClient *redis.Redis ArticleModel model.ArticleModel}
func NewServiceContext(c config.Config) *ServiceContext { return &ServiceContext{ Config: c, ArticleModel: model.NewArticleModel(sqlx.NewMysql(c.DB.DataSource), c.Cache), }}
复制代码


至此都配置好了, 接下来就是编写业务逻辑代码

6 | 编写 api 层和 rpc 层下 logic 代码


这里我就拿增加文章做示例

首先编写 api 下的 logic 中的 createArticleLogic.go 文件:

package article
import ( "GoZeroDemo/app/article/cmd/rpc/article" "context"
"GoZeroDemo/app/article/cmd/api/internal/svc" "GoZeroDemo/app/article/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx")
type CreateArticleLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext}
func NewCreateArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateArticleLogic { return &CreateArticleLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, }}
func (l *CreateArticleLogic) CreateArticle(req *types.CreateArticleReq) (resp *types.CreateArticleResp, err error) { // 这里就是调用rpc下的AddArticle方法 _, err = l.svcCtx.ArticleRpc.AddArticle(l.ctx, &article.AddArticleReq{ Title: req.Title, Content: req.Content, }) if err != nil { return nil, err } return
return}
复制代码


接下来完成 rpc 中的 AddArticle 方法, 编写 addArticleLogic.go 文件:


package logic
import ( "GoZeroDemo/app/article/cmd/rpc/internal/svc" "GoZeroDemo/app/article/cmd/rpc/pb" "GoZeroDemo/app/article/model" "context"
"github.com/zeromicro/go-zero/core/logx")
type AddArticleLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger}
func NewAddArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddArticleLogic { return &AddArticleLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), }}
// -----------------------article-----------------------func (l *AddArticleLogic) AddArticle(in *pb.AddArticleReq) (*pb.AddArticleResp, error) { article := new(model.Article) article.Title = in.Title article.Content = in.Content // 调用model层的方法 _, err := l.svcCtx.ArticleModel.Insert(l.ctx, article) if err != nil { return nil, err } return &pb.AddArticleResp{}, nil}
复制代码


接下来就可以进行测试了

7 | 自动生成接口文档并测试(使用 Apifox)

  1. 使用 swagg 生成 json 文件下载 goctl-swagger, 确认安装是否成功:


go get -u github.com/zeromicro/goctl-swaggergoctl-swagger -v
复制代码


在 main.api 下打开 Terminal, 输入以下代码:


goctl api plugin -plugin goctl-swagger="swagger -filename main.json" -api main.api -dir .
复制代码


不出意外就会生成一个 main.json 文件



  1. 将 json 文件导入到 Apifox 中打开 Apifox, 新建接口项目, 点击这里导入 json 文件



将 json 文件拖进去即可


完成之后-->点击这里-->进入选择开发环境-->进行一个端口的配置




这里的地址就是我对应的 api 服务的地址(yaml 文件中配置)3. 启动程序后, 进行测试还记得刚刚我改名的 main.go 文件吗,一个在 api 层,一个在 rpc 层,现在分别运行它们



将它们同时在控制台 Terminal 打开,分别运行命令 go run main.go




可以看到它们监听了两个端口,一个 1001 一个 2001 接下来就可以在 Apifox 中进行测试了从左至右分别点击这三个地方(数据可以自动生成也可以自己写)



然后发现返回 null 和 200(因为我没有定义规范的返回给前端的字段,所以返回 null 代表正常)4. 查询数据库,确保数据生成最后查看数据库中是否出现了这条记录



可以看到记录新增成功, 圆满完成!

总结

这篇文章分享了如何使用 gozero 开发文章服务的增加功能,强烈建议你跟着我的步骤操练一遍,也可以尝试用相同的思路实现删除、查询功能。


我将继续更新 Go-Zero 系列文章,如果你对 Go 语言或者微服务感兴趣,欢迎关注我的公众号,也欢迎直接私信我。

发布于: 刚刚阅读数: 3
用户头像

王中阳Go

关注

靠敲代码在北京买房的程序员 2022-10-09 加入

【微信】wangzhongyang1993【公众号】程序员升职加薪之旅【成就】InfoQ专家博主👍掘金签约作者👍B站&掘金&CSDN&思否等全平台账号:王中阳Go

评论

发布
暂无评论
Go-Zero从0到1实现微服务项目开发(二)_Go_王中阳Go_InfoQ写作社区