您现在的位置是:首页 > 唯美句子

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

作者:晨起时间:2024-05-03 11:27:10分类:唯美句子

简介  文章浏览阅读1.1k次,点赞9次,收藏9次。继续更新GoZero微服务实战系列文章:上一篇被GoZero作者万总点赞了,本文将继续使用 Go-zero 提供的工具和组件,从零开始逐步构建一个基本的微服务项目。手把手带你完成:项目初始化+需求分析+表结构设计+a

点击全文阅读

前言

书接上回,继续更新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文件有自定义的修改之后, 就不建议使用这个工具了, 使用方法如下

安装最新的sql2pb
go install github.com/Mikaelemmmm/sql2pb@latest
命令示例:
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 configimport (   "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 svcimport (   "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 configimport (   "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 svcimport (   "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 articleimport (   "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 logicimport (   "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)

使用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文件

将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语言或者微服务感兴趣,欢迎关注我的公众号,也欢迎直接私信我。

点击全文阅读

郑重声明:

本站所有活动均为互联网所得,如有侵权请联系本站删除处理

我来说两句