安装
安装 goctl
go install github.com/zeromicro/go-zero/tools/goctl@latest
安装完成后在你的 ${GOPATH}/bin
目录下会有一个 goctl.exe
文件, 执行 goctl --version
出现版本信息即安装成功 (如果出现类似于找不到命令的报错的话, 那么需要将 ${GOPATH}/bin
目录添加到环境变量中)
PS D:\goprojects> goctl --version
goctl version 1.5.4 windows/amd64
安装工具包
goctl env check --install --verbose --force
这里可能会因为某些原因安装失败, 如果是 windows 系统的话, 那可以直接在 这里 下载压缩包, 下载完成后只需要将压缩包中的文件夹移到
${GOPATH}
目录下即可
其他系统的话可以选择手动安装三个工具:
protoc 需要前往 github
下载安装包, 然后同样直接把安装包里面的文件放到你的 ${GOPATH}
目录下即可
# proto-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
安装完成后进行验证
PS D:\goprojects> goctl env check --verbose
[goctl-env]: preparing to check env
[goctl-env]: looking up "protoc"
[goctl-env]: "protoc" is installed
[goctl-env]: looking up "protoc-gen-go"
[goctl-env]: "protoc-gen-go" is installed
[goctl-env]: looking up "protoc-gen-go-grpc"
[goctl-env]: "protoc-gen-go-grpc" is installed
[goctl-env]: congratulations! your goctl environment is ready!
安装 gozero
在一个有 go mod 的项目下执行 go get
获取 gozero
$ mkdir usercenter && cd usercenter
$ go mod init usercenter
$ go get -u github.com/zeromicro/go-zero@latest
如果报错的话可能是因为没有开启 gomod 或者是网络问题:
$ go env -w GO111MODULE=on # 开启 gomod 模式
$ go env -w GOPROXY=https://goproxy.cn,direct # 设置代理
单体服务写法
编写 api 文件
gozero 是根据 api 文件 来生成代码, 所以我们使用上面生成的 usercenter 项目, 并写一个简单的 api demo
在 usercenter
目录下新建 api
目录, 在 api
目录中新建 user.api
文件, 写入以下内容
syntax = "v1"
info(
title: "Usercenter API"
desc: "API for usercenter"
author: "GuoChenxu"
email: "2269409349@qq.com"
version: "1.0"
)
// 定义数据结构
type (
PingReq {
Id int64 `path:"id"`
}
PingResp {
Pong string `json:"string"`
}
)
// 这里定义了路径前缀, 此外还可以定义jwt 开关、中间件、路由分组、路由前缀等
// server 对下面 service 中的所有服务有效
@server(
prefix: user
)
// 定义具体的服务请求路径
service user {
@doc "ping"
@handler ping
get /ping/:id (PingReq) returns (PingResp)
}
参数的 tag 和传参形式的对应:
tag | 传参形式 |
---|---|
path | Path 传参 |
form | Query 传参 |
json | Body 传参 |
生成代码
在 api 文件所在目录下生成代码
# --api 指定 api 文件
# --dir 指定生成代码目录
# --style 指定命名风格
PS D:\goprojects\src\usercenter\api> goctl api go --api .\user.api --dir .\ --style=go_zero
Done.
注意, 有些同学
比如我用了 gowork 管理项目, 那么在生成代码之前需要将项目加到 gowork 文件中 具体代码如下:# .\src\ 是你的项目目录 go work use -r .\src\
现在的文件目录如下:
D:\GOPROJECTS\SRC\USERCENTER
│ go.mod
│ go.sum
│
└─api
│ user.api # api 文件
│ user.go # 项目入口文件
│
├─etc
│ user.yaml # 配置文件
│
└─internal
├─config
│ config.go # 读取配置
│
├─handler # 路由
│ ping_handler.go
│ routes.go
│
├─logic # 核心逻辑
│ ping_logic.go
│
├─svc # 上下文
│ service_context.go
│
└─types # 项目中的数据结构
types.go
编写逻辑代码
gozero 的魅力在于他几乎生成了所有其他的代码, 你只需要关注最核心的逻辑代码
打开 internal/logic/ping_logic.go
开始编写代码
func (l *PingLogic) Ping(req *types.PingReq) (resp *types.PingResp, err error) {
id := strconv.FormatInt(req.Id, 10)
return &types.PingResp{
Pong: "pong: " + id,
}, nil
}
运行项目
PS D:\goprojects\src\usercenter\api> go run .\user.go
Starting server at 0.0.0.0:8888...
因为默认的 json 格式日志不好看, 所以我们在 etc/user.yaml
中修改日志格式
Name: user
Host: 0.0.0.0
Port: 8888
Log:
Encoding: plain
成功响应:
日志打印:
至此一个简单的单体 demo 就写完了
rpc 服务写法
编写 proto 文件
与 api 文件类似, rpc 是根据 proto 文件 生成代码
在 usercenter
目录下新建 rpc
目录, 在 rpc
目录中新建 user.proto
文件, 写入以下功能
syntax = "proto3";
package pb;
option go_package="./pb";
// 定义消息类型
message Request {
int64 id = 1;
}
message Response {
string Pong = 1;
}
// 定义服务
service userrpc {
rpc Ping(Request) returns(Response);
}
生成代码
在 proto 文件目录下生成代码
# protoc 指定 proto文件
# *_out 指定代码文件的输出目录
PS D:\goprojects\src\usercenter\rpc> goctl rpc protoc .\user.proto --go_out=.\ --go-grpc_out=.\ --zrpc_out=.\ --style=go_zero
Done.
文件目录
D:\GOPROJECTS\SRC\USERCENTER
│ go.mod
│ go.sum
│
├─api
│
└─rpc
│ user.go
│ user.proto
│
├─etc
│ user.yaml
│
├─internal
│ ├─config
│ │ config.go
│ │
│ ├─logic
│ │ ping_logic.go
│ │
│ ├─server
│ │ userrpc_server.go
│ │
│ └─svc
│ service_context.go
│
├─pb
│ user.pb.go
│ user_grpc.pb.go
│
└─userrpc
userrpc.go
安装 etcd
rpc 默认生成的代码是使用 etcd 注册发现服务的, 所以还需要安装 etcd
前往 github 下载合适的版本, 解压后放在合适的目录下, 并添加进环境变量
验证安装成功
PS D:\Tools\etcd> etcd --version
etcd Version: 3.5.9
Git SHA: bdbbde998
Go Version: go1.19.9
Go OS/Arch: windows/amd64
启动 etcd
如果你在尝试了 下载最新版本、使用管理员权限运行、启动端口没有被占用、关闭防火墙 之后仍旧无法正常启动 etcd, 那么请重启电脑后再次运行
编写逻辑代码
编写 rpc
目录下的 internal/logic/ping_logic.go
func (l *PingLogic) Ping(in *pb.Request) (*pb.Response, error) {
id := strconv.FormatInt(in.Id, 10)
return &pb.Response{
Pong: "pong: " + id,
}, nil
}
运行项目
修改一下项目的运行端口, etcd 的监听地址和 log 格式
Name: user.rpc
ListenOn: 0.0.0.0:8889
Etcd:
Hosts:
- 0.0.0.0:2379
Key: user.rpc
Log:
Encoding: plain
运行项目
单独测试 rpc 服务
你可以对每个 rpc 服务都写一个客户端进行测试, 但是这样过于繁琐, 所以我们希望可以单独对 rpc 服务进行测试
这里推荐 apifox (最新版), 可以像 http 接口一样测试 rpc 服务
-
点击新建项目, 选择新建 gRpc 项目
-
点击左上角加号, 直接导入 proto 文件
-
然后就可以像普通的 http 接口一样发送请求进行测试
测试成功
单体项目升级成微服务
在编写了 rpc 服务之后, 我们可以将之前的 api 单体服务升级成微服务项目
服务发现
现在下述操作均在 api
目录下执行
打开 etc/user.yaml
增加如下配置
Name: user
Host: 0.0.0.0
Port: 8888
Log:
Encoding: plain
# 客户端 etcd 配置
UserRpcConfig:
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc
在 internal/config/config.go
文件中增加配置
package config
import (
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/zrpc"
)
type Config struct {
rest.RestConf
UserRpcConfig zrpc.RpcClientConf // 读取 rpc 配置
}
在 internal/svc/service_context.go
文件中增加代码
package svc
import (
"usercenter/api/internal/config"
"usercenter/rpc/userrpc"
"github.com/zeromicro/go-zero/zrpc"
)
type ServiceContext struct {
Config config.Config
UserRpcClient userrpc.Userrpc // 注册 rpc 客户端
}
func NewServiceContext(c config.Config) *ServiceContext {
return &ServiceContext{
Config: c,
UserRpcClient: userrpc.NewUserrpc(zrpc.MustNewClient(c.UserRpcConfig)),
}
}
至此客户端的服务发现已经配置完成
修改核心代码
升级成微服务后就要将逻辑代码交给 rpc 服务端去做, 客户端需要给服务端发送请求, 所以需要修改核心的逻辑代码
修改 api
目录下的 internal/logic/ping_logic.go
文件
func (l *PingLogic) Ping(req *types.PingReq) (resp *types.PingResp, err error) {
// 向服务端发送请求
pong, err := l.svcCtx.UserRpcClient.Ping(l.ctx, &userrpc.Request{
Id: req.Id,
})
return &types.PingResp{
Pong: pong.GetPong(),
}, err
}
运行项目
先运行服务端, 再运行客户端
测试成功
查看日志, 确实是服务端接受请求并处理
至此 gozero 的快速入门就结束了, 后续会有文章讲述 在 gozero 中使用 gorm, gozero 的 api 文件编写 以及 在 gozero 中使用 nacos 进行服务的注册发现等 咕咕咕, 先立个 flag