微服务效率工具 goctl 深度解析

目录
  • 前言
  • goctl 的由来
    • 1. goctl 的诞生
    • 2. 为什么需要 goctl?
    • 3. 怎么理解开发规范?
    • 4. 怎么理解工程效率?
  • 二 、goctl 的安装及功能介绍
    • 1. 介绍
  • 2. 安装
    • go get/install
    • docker
  • 3. 功能介绍
    • goctl completion
      • 1.3.5
      • 1.3.6
    • goctl migrate
    • goctl env
    • 1. 环境查看
    • 2. 修改参数
    • 3. 依赖检测/安装
    • goctl rpc
    • 4. 编辑器插件
  • 三、goctl 使用中遇到的问题
    • 1. 386 架构上安装 goctl 失败!
    • 2. grpc 到底安装什么版本插件?
    • 3. 为什么 Windows 上生成 api/zrpc 代码时,总是提示 The system cannot find the path specified 类似错误?
    • 4. No help topic 'proto'
    • 5. zrpc 生成代码时报 go_package 错误
    • 6. zrpc 生成代码时指定了 pb 的输出目录为当前服务 main 目录
    • 7. 为什么我的代码生成的 pb client(不)带 client 标志?
    • 8. 为什么我生成的目录结构和文档演示不一样?
    • 9. 为什么我安装了 goctl 编辑器插件还是不能高亮

前言

本文根据 安前松 的视频分享整理而来,视频回放地址如下:

www.bilibili.com/video/BV1Hr…

goctl 的由来

1. goctl 的诞生

goctl 的最早功能是为了解决 GRPC 内网调试问题,大约是在 2019 年,在我们的生产环境中,rpc 是内网隔离的,不可通过外网访问,为了快速去 mock 一些线上 RPC client 的请求,就简单的实现了第一版本的代码生成,主要目的是去访问 RPC Server 做一些调试。

2. 为什么需要 goctl?

  • 降低沟通成本

    沟通,是团队协作进行信息交换的一种形式,沟通的方式有很多种,会议沟通、文档沟通、聊天交流,相信不管是哪种方式,沟通都是团队中最难的一个环节,会议沟通需要占用大量时间,动则半小时起步,文档沟通同样,也会占据大量时间去构思和编写大篇幅的文档,最后可能还没表达出预期目标,线上聊天,需要双方都在线上才能进行信息交换,当然我们这里沟通交换的信息更多是指开发中的一些内容,如接口信息、部署信息等。

  • 降低团队耦合

    有了沟通,那么团队之间的协作的耦合是避免不了的,例如:在前后端开发中,最大的耦合是接口的耦合,前端完成了规定 UI 绘制后,需要等待后端的接口部署到对应环境才能实现功能的调试,在此期间,前端的团队资源就会大大浪费,由此还会导致项目的延期等问题。

  • 提高开发效率

    除了沟通成本和团队耦合以外,每个团队在进行项目开发时也有很多时间是在做重复的工作,例如:我们在开发一个新的功能时,需要去定义接口,编写接口文档,编码准备工作,业务开发,model 文件,编写 Dockerfile 文件,编写 k8s yaml 文件,在这些上面我们可以在每个环节上都有提升的空间,让用户将真正的时间集中在业务开发上。

  • 降低错误率

    在之前的开发实践中,经常会出现 grpc server 实现不完全的问题,grpc server 实现类经常会出现编译不过的情况;除此之外,数据库查询层代码开发,sql 语句的编写多参,少参,参数错位,在编译过程中很难发现,一般可能到 QA 环节才能发现,更甚者会导致线上问题。

3. 怎么理解开发规范?

开发规范,包括编码规范,工程规范,提交规范,代码审核规范,部署规范等等,团队内如果将开发规范统一起来,其收益可想而知,举个例子:假如你所在的公司没有统一开发规范,这时需要你去做一些跨部门协作或者支持,焕然一新的开发环境让你望而却步,还没开始就有了抵触的念头,这岂不是违背了支持的初衷。

4. 怎么理解工程效率?

工程效率,要理解工程效率,可以先看看『效率』的定义:

效率是指单位时间内完成的工作量

效率的目标是快,但快并不是效率,换句话说就是在单位时间内完成的高质量工作,这才是我们要追求的目标,那么工程效率就是为了『缩短从开发到线上的距离』

二 、goctl 的安装及功能介绍

1. 介绍

  • goctl 定义

    goctl 定义,准确说是定位吧,可以理解为一个代码生成脚手架,其核心思想是通过对 DSL 进行语法解析、语义分析到数据驱动实现完成代码生成功能,旨在帮助开发者从工程效率角度提高开发者的开发效率。

  • 解决的问题
    • 提高开发效率:goctl 的代码生成覆盖了Go、Java、Android、iOS、TS 等多门语言,通过 goctl 可以一键生成各端代码,让开发者将精力集中在业务开发上。
    • 降低沟通成本:使用 zero-api 替代 API 文档,各端以 zero-api 为中心生成各端代码,无需再通过会议、API 文档来进行接口信息传递。
    • 降低耦合度: 在之前的开发实践中,没有 goctl 之前,我们采用的是传统的 API 文档来作为接口信息传递的载体,然后通过会议来进行二次 review,我们都知道,前端开发工作中,除了 UI 的绘制外就是 UI 联调,如果比较积极的前端开发者,可能会自己利用一些脚手架或者自己 mock 一些数据去进行 UI 联调,反之,也有原地等待后端部署后再联调的 case,原因是自己写 mock 数据太耗时,也不想去动,如果前端的开发进度在后端之前,那么在后端部署到环境中这期间,前端只能安静的原地等待,这不仅是一种资源的浪费,也会造成项目进度的延期,有了 zero-api ,前端可以利用 goctl 去生成适量的 mock 数据来进行 UI联调。
  • 发展历史

goctl 发展历史可以大概的过一下,挑几个标志性的功能讲讲吧!

首先是 goctl rpc,goctl rpc 的第一版本就是 goctl 的雏形,主要是为了生成 client 代码对 rpc 做调试使用,具体就不展开了。goctl rpc 的发展经过了很多曲折,印象比较深刻的应该算 goctl rpc proto 向 goctl rpc protoc 的转变,这期间为了解决很多问题,才做了相应的变更,具体细节在分享 rpc 代码生成使用那块再详细分享,在这里面其实对我来说印象最深刻的一个功能算是 goctl model 了,其算是我开始维护 goctl 的一个入手点吧,也是我从业务开发实践中挖掘的解决方案吧,终究我还是比较 "懒",记得在当时开发一个业务模块,由于业务比较大,需要创建的数据表也很多,在没有 goctl 前都是自己去手动编码完成,这一块我记忆犹新,花了仅一天的时间来写 model 文件,因为我没有用 orm 的习惯,所以这块 sql 完全是裸 sql 语句,服务跑起来后才发现有很多 sql 传参上的错误,基本都是多参少参问题,除此之外,每次新增索引,或者字段变更,缓存的相关逻辑维护也让我十分头疼,于是结合当时的开发最佳实践,将其按照缓存与否把这块的工作交给了 goctl,第一版本 goctl model 生成主要是网页版本,后面陆续集成到 goctl 里了,这给我后续开发带来了很大的开发效率收益。

  • 展望未来

    goctl 集成了比较多的功能,其基本是以代码生成为主,开发规范为辅,goctl 是围绕 zero-api 为中心做代码生成的,因此在将来,zero-api 的建设会成为我们的重心:

    • ast 的改造:替换原有比较重的 antlr4,可以解决很多人安装 goctl 时 内存不够,系统架构不支持的各种问题,这
    • goctl mock 的支持,最大限度解耦各端依赖耦合

2. 安装

Goctl 安装有两种方式,分别是 go get 或者 go install,其次是 docker。

go get/install

# Go 1.16 之前版本
$ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/goctl@latest
# Go 1.16 及以后版本
$ GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest
# macOS
$ brew install goctl
# 验证
$ goctl --version
goctl version 1.3.5 darwin/amd64
# 查看 goctl
$ cd $GOPATH/bin && ls | grep "goctl"

如果执行 goctl --version 提示 command not found: goctl 的错误,请先排查 $GOBIN 是否在环境变量下。

docker

# 1. pull
$ docker pull kevinwan/goctl
....
# 2. ls
$ docker image ls | grep "goctl"
kevinwan/goctl        latest    7fd46843de3d   5 weeks ago    383MB
# 3. run
$ docker run -it kevinwan/goctl /bin/sh

3. 功能介绍

我们接下来看看功能介绍,通过指令 goctl --help 可以列出我们当前已经支持的功能,可能大家在看文档时也没有专心下来对这块指令做研究,只是用到一些高频指令,今天既然是 goctl 的专题分享,我们就花点时间来一起过过,带着大家从 0 到 1 熟悉 goctl。

$ goctl --help
A cli tool to generate api, zrpc, model code
Usage:
goctl [command]
Available Commands:
api         Generate api related files
bug         Report a bug
completion  Generate the autocompletion script for the specified shell
docker      Generate Dockerfile
env         Check or edit goctl environment
help        Help about any command
kube        Generate kubernetes files
migrate     Migrate from tal-tech to zeromicro
model       Generate model code
quickstart  quickly start a project
rpc         Generate rpc code
template    Template operation
upgrade     Upgrade goctl to latest version
Flags:
-h, --help      help for goctl
-v, --version   version for goctl
Use "goctl [command] --help" for more information about a command.

goctl 的功能比较丰富,所以难免指令参数比较多,大家在使用时除了看文档外,也善用 --help 这个flag,因为他会告诉你每个指令或者子指令的用法,需要什么参数,参数类型是字符串还是布尔,是必填还是可选,切不可自己猜测他应该用什么 flag,虽然 goctl 是我自己主要维护,其实很多时候,有些指令比较文档,没有太多 feature 去更新,我也记不住,我也是通过 --help 去查看功能介绍的

goctl completion

查看 goctl 版本

$ goctl --version
goctl version 1.3.5 darwin/amd64

1.3.5

本节内容仅适合 goctl 版本在 1.3.5及之前的的自动补全设置参考,1.3.5版本及之前仅支持类 Unix 操作系统,不支持 Windows 的自动补全,1.3.5 之后的请跳过此节内容

  • 执行 goctl completion -h 查看使用说明
$ goctl completion --help
   NAME:
   goctl completion - generation completion script, it only works for unix-like OS
USAGE:
goctl completion [command options] [arguments...]
OPTIONS:
--name value, -n value  the filename of auto complete script, default is [goctl_autocomplete]

根据帮助说明得知,goctl completion 支持通过 --name 传递一个参数生成自动补全脚本文件名,但该参数为非必填,默认不填时为goctl_autocomplete 文件,其位于 $GOCTLHOME 目录下。

  • 执行 goctl completion 来生成自动补全脚本
$ goctl completion
generation auto completion success!
executes the following script to setting shell:
echo PROG=goctl source /Users/keson/.goctl/.auto_complete/zsh/goctl_autocomplete >> ~/.zshrc && source ~/.zshrc
# 或者
echo PROG=goctl source /Users/keson/.goctl/.auto_complete/bash/goctl_autocomplete >> ~/.bashrc && source ~/.bashrc
  • 查看当前 shell
$ echo $SHELL
/bin/zsh
  • 选择对应 shell 的脚本执行,我这里为 zsh,所以执行指令如下
$ echo PROG=goctl source /Users/keson/.goctl/.auto_complete/zsh/goctl_autocomplete >> ~/.zshrc && source ~/.zshrc
  • 重启终端验证结果
# 键入 goctl 后按下 tab 键查看自动补全提示
$ goctl # tab
api            -- generate api related files
bug            -- report a bug
completion     -- generation completion script, it only works for unix-like OS
docker         -- generate Dockerfile
env            -- check or edit goctl environment
help        h  -- Shows a list of commands or help for one command
kube           -- generate kubernetes files
migrate        -- migrate from tal-tech to zeromicro
model          -- generate model code
rpc            -- generate rpc code
template       -- template operation
upgrade        -- upgrade goctl to latest version

1.3.6

本节内容仅适合 goctl 版本在 1.3.6 及之后的的自动补全设置参考,1.3.6 之前的请跳过此节内容

  • 如果你是从 1.3.5 升级到 1.3.6 及以后,则需要执行如下指令来清除旧版本自动补全配置,这里以 zsh 为例子,否则请跳过这一步
# 编辑 ~/.zshrc
$ vim ~/.zshrc
# 找到 PROG=goctl 所在行并删除
# source
$ source ~/.zshrc && rm .zcompdump*
# 重启终端
  • 执行 goctl completion -h 查看使用说明,从使用帮助中可以查看到目前支持 bash、fish 、powershell、zsh 4 种 shell 的自动补全。
$ goctl completion --help
Generate the autocompletion script for goctl for the specified shell.
See each sub-command's help for details on how to use the generated script.
Usage:
goctl completion [command]
Available Commands:
bash        Generate the autocompletion script for bash
fish        Generate the autocompletion script for fish
powershell  Generate the autocompletion script for powershell
zsh         Generate the autocompletion script for zsh
Flags:
-h, --help   help for completion
Use "goctl completion [command] --help" for more information about a command.
  • 查看当前使用的 shell
$ echo $SHELL
/bin/zsh
  • 由于当前使用的 zsh,所以我们来看一下 zsh 的自动补全设置帮助
$ goctl completion zsh --help
Generate the autocompletion script for the zsh shell.
If shell completion is not already enabled in your environment you will need
to enable it.  You can execute the following once:
        echo "autoload -U compinit; compinit" >> ~/.zshrc
To load completions for every new session, execute once:
#### Linux:
        goctl completion zsh > "${fpath[1]}/_goctl"
#### macOS:
        goctl completion zsh > /usr/local/share/zsh/site-functions/_goctl
You will need to start a new shell for this setup to take effect.
Usage:
goctl completion zsh [flags]
Flags:
-h, --help              help for zsh
--no-descriptions   disable completion descriptions

从上文可以看出,根据操作系统的不同,自动补全的设置方式也不一样,我这里是 macOS,我们执行一下对应的指令:

$ goctl completion zsh > /usr/local/share/zsh/site-functions/_goctl

我们先重开一个终端来试一下:

# 键入 goctl 后按下 tab 键查看自动补全提示
$ goctl # tab
api         -- Generate api related files
bug         -- Report a bug
completion  -- Generate the autocompletion script for the specified shell
docker      -- Generate Dockerfile
env         -- Check or edit goctl environment
help        -- Help about any command
kube        -- Generate kubernetes files
migrate     -- Migrate from tal-tech to zeromicro
model       -- Generate model code
quickstart  -- quickly start a project
rpc         -- Generate rpc code
template    -- Template operation
upgrade     -- Upgrade goctl to latest version

常见错误

  • goctl Error: unknown flag: --generate-goctl-completion
  • (eval):1: command not found: _goctl 按照 1.3.6 自动补全配置重新进行配置

goctl migrate

帮助开发者从1.3.0 之前版本无缝迁移到 1.3.0及后的任意版本,如果使用的 go-zero 版本本身就是 1.3.0 及之后的,则无需做此操作。

为什么需要迁移?

go-zero 在 1.3.0 版本做了组织变更,即用 zeromicro 替换原来的 tal-tech 组织名称。

我现在有一个演示项目 awesomemigrate 是用旧版本 goctl 生成的,该项目的 go-zero 的 module 为

module awesomemigrate
go 1.18
require github.com/tal-tech/go-zero v1.2.5
...

假设我们需要将该项目的 go-zero 升级至截止目前最新版本 1.3.3 ,要完成项目从 tal-tech 到 zeromicro 的升级 前需要确保 goctl 版本大于 v1.3.2,然后在执行 goctl 迁移指令执行,如果 goctl 版本小于 v1.3.2,则需要升级。

# 1. 查看当前 goctl 版本
$ goctl --version
goctl version 1.2.5 darwin/amd64
# 2. 由于 goctl 版本小于 v1.3.2,则需要升级至最新,如果 goctl 版本已经是1.3.2及之后了,则可以不用升级
$ go install github.com/zeromicro/go-zero/tools/goctl@latest
# 3. 查看一下迁移指令使用帮助
$ goctl migrate --help
NAME:
goctl migrate - migrate from tal-tech to zeromicro
USAGE:
goctl migrate [command options] [arguments...]
DESCRIPTION:
migrate is a transition command to help users migrate their projects from tal-tech to zeromicro version
OPTIONS:
--verbose, -v    verbose enables extra logging
--version value  the target release version of github.com/zeromicro/go-zero to migrate
# 4. 进入待迁移的项目下,执行迁移指令
$ goctl migrate --version 1.3.3
# 5. 验证依赖是否存在问题
$ go test .
?       awesomemigrate  [no test files]

迁移完成后,我们再来看看 module 文件

module awesomemigrate
go 1.18
require github.com/zeromicro/go-zero v1.3.3
...

在 project 搜索一下 tal-tech的匹配结果会发现为0:

goctl env

goctl env 主要是用于环境检测、安装、环境参数控制等功能,除此之外还可以查看当前 goctl 的一些环境信息,以至于用户在遇到 bug 时可以根据此环境上报当前 goctl 处于的环境。

首先我们看看其使用说明

$ goctl env --help
NAME:
goctl env - check or edit goctl environment
USAGE:
goctl env command [command options] [arguments...]
COMMANDS:
install  goctl env installation
check    detect goctl env and dependency tools
OPTIONS:
--write value, -w value  edit goctl environment
--help, -h               show help

goctl env 支持环境查看、参数修改、依赖检测安装几个功能,我们依次来看一下

1. 环境查看

在不输入任何 flag 的情况下,则是查看当前 goctl 环境。

$ goctl env
GOCTL_OS=darwin
GOCTL_ARCH=amd64
GOCTL_HOME=/Users/keson/.goctl
GOCTL_DEBUG=false
GOCTL_CACHE=/Users/keson/.goctl/cache
GOCTL_VERSION=1.3.5
PROTOC_VERSION=3.19.4
PROTOC_GEN_GO_VERSION=v1.27.1
PROTO_GEN_GO_GRPC_VERSION=1.2.0

以上参数的大概说明为

参数名称 参数类型 参数说明
GOCTL_OS STRING 当前操作系统,常见值有 darwin、windows、linux 等
GOCTL_ARCH STRING 当前系统架构,常见值有 amd64, 386 等
GOCTL_HOME STRING 默认为 ~/.goctl
GOCTL_DEBUG BOOLEAN 是否开启 debug 模式,默认为 false,目前暂未使用,主要是 goctl 开发中可能用于控制调试模式
GOCTL_CACHE STRING goctl 缓存目录,主要缓存下载的依赖 protoc、protoc-gen-go、protoc-gen-go-grpc等
GOCTL_VERSION STRING 当前 goctl 版本
PROTOC_VERSION STRING 当前 protoc 版本,如未安装则为空字符串
PROTOC_GEN_GO_VERSION STRING 当前 protoc-gen-go 版本,如未安装或者从github.com/golang/protobuf 安装版本为 v1.3.2 之前的则为空字符串
PROTO_GEN_GO_GRPC_VERSION STRING 当前 protoc-gen-go-grpc版本,如未安装则为空字符串

2. 修改参数

比如我们将 GOCTL_DEBUG 修改为 true

# 修改前
$ goctl env | grep 'GOCTL_DEBUG'
GOCTL_DEBUG=false
# 修改 GOCTL_DEBUG 为 true
$ goctl env -w GOCTL_DEBUG=true
# 修改后
goctl env | grep 'GOCTL_DEBUG'
GOCTL_DEBUG=true

3. 依赖检测/安装

我们来检测一下我当前的依赖都是否安装好,目前依赖检测内容为protoc、protoc-gen-go、protoc-gen-go-grpc

# 我们来检查一下依赖安装
$ goctl env check --verbose
[goctl-env]: preparing to check env
[goctl-env]: looking up "protoc"
[goctl-env]: "protoc" is not found in PATH
[goctl-env]: looking up "protoc-gen-go"
[goctl-env]: "protoc-gen-go" is not found in PATH
[goctl-env]: looking up "protoc-gen-go-grpc"
[goctl-env]: "protoc-gen-go-grpc" is not found in PATH
[goctl-env]: check env finish, some dependencies is not found in PATH, you can execute
command 'goctl env check --install' to install it, for details, please execute command
'goctl env check --help'
# 安装依赖,安装依赖有2中方式
# 方式一
# $ goctl env check --install --force --verbose
# 方式二
$ goctl env install --verbose -f
[goctl-env]: preparing to check env
[goctl-env]: looking up "protoc"
[goctl-env]: "protoc" is not found in PATH
[goctl-env]: preparing to install "protoc"
[goctl-env]: "protoc" is already installed in "/Users/keson/go/bin/protoc"
[goctl-env]: looking up "protoc-gen-go"
[goctl-env]: "protoc-gen-go" is not found in PATH
[goctl-env]: preparing to install "protoc-gen-go"
[goctl-env]: "protoc-gen-go" is already installed in "/Users/keson/go/bin/protoc-gen-go"
[goctl-env]: looking up "protoc-gen-go-grpc"
[goctl-env]: "protoc-gen-go-grpc" is not found in PATH
[goctl-env]: preparing to install "protoc-gen-go-grpc"
[goctl-env]: "protoc-gen-go-grpc" is already installed in "/Users/keson/go/bin/protoc-gen-go-grpc"
[goctl-env]: congratulations! your goctl environment is ready!

goctl rpc

首先我们来看一下该指令的使用帮助

goctl rpc -h
Generate rpc code
Usage:
goctl rpc [flags]
goctl rpc [command]
Available Commands:
new         Generate rpc demo service
protoc      Generate grpc code
template    Generate proto template
Flags:
--branch string   The branch of the remote repo, it does work with --remote
-h, --help            help for rpc
--home string     The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--o string        Output a sample proto file
--remote string   The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
Use "goctl rpc [command] --help" for more information about a command.

该指令提供了三个子指令,new 是快速创建一个 zrpc 服务,protoc 是根据 proto 描述文件生成 zrpc 代码,而 template 则是快速生成一个 proto 模板,我们将重点围绕 goctl rpc protoc 指令来展开,看看 goctl rpc protoc 的使用说明:

goctl rpc protoc -h
Generate grpc code
Usage:
goctl rpc protoc [flags]
Examples:
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
Flags:
--branch string     The branch of the remote repo, it does work with --remote
-h, --help              help for protoc
--home string       The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
--remote string     The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--style string      The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
-v, --verbose           Enable log output
--zrpc_out string   The zrpc output directory

goctl rpc protoc 到底怎么使用,为什么示例里面有 --go_out、--go-grpc_out 参数,而查看 help 的时候却没有看到介绍?目前我们先这样理解,我们先抛开 goctl,根据官方 protoc 生成 grpc 代码时的指令是什么?会用到哪些 flag,对于 zrpc 的代码生成,你可以理解为 goctl 生成 zrpc 只是在生成 grpc 代码指令的基础上加了 goctl rpc 前缀和一些 goctl 生成 zrpc 需要的 flag,而对于 protoc 及 插件 protoc-gen-go 、 protoc-gen-grpc-go 的相关参数 goctl 只是做继承,没有必要显示的在 help 里面再描述一遍,后面在分析源码时可以给大家详细讲解一些这块的设计和考虑,接下来我们用一个例子来演示一下,假设我们有一个 greet.proto 文件,抛开 goctl ,我们生成 grpc 代码需要执行的指令如下:

如果不知道 grpc 代码是怎么生成的,这块建议参考官方文档 grpc.io/

# 进入 greet.proto 所在目录
$ protoc greet.proto --go_out . --go-grpc_out .
$ tree
.
├── greet.proto
└── pb
├── greet.pb.go
└── greet_grpc.pb.go

那么按照上文对 goctl rpc protoc 的介绍,我们生成 zrpc 代码的指令则应该为

# 这里多了一个 --zrpc_out 用于指定 zrpc 代码的输出目录
$ goctl rpc protoc greet.proto --go_out=. --go-grpc_out=. --zrpc_out=. --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!
[command]: protoc greet.proto --go_out . --go-grpc_out .
Done.
$ tree
.
├── etc
│   └── greet.yaml
├── go.mod
├── greet
│   └── greet.go
├── greet.go
├── greet.proto
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   └── pinglogic.go
│   ├── server
│   │   └── greetserver.go
│   └── svc
│       └── servicecontext.go
└── pb
├── greet.pb.go
└── greet_grpc.pb.go
8 directories, 11 files

如果在生成代码时需要输出日志,可以加 --verbose 来显示日志。

goctl rpc protoc 在生成 zrpc 代码时会先对你的环境依赖进行检测,如果没有安装则会自动安装依赖再生成代码。

4. 编辑器插件

为了提升大家对 zero-api 文件的编写效率,我们分别对 intellij 和 vscode 提供了相应的编辑器插件, intellij 插件介绍及使用请参考 github.com/zeromicro/g… vscode 插件介绍及使用请参考 github.com/zeromicro/g…

三、goctl 使用中遇到的问题

goctl 从最初的一个功能 rpc proxy 到当前版本(v1.3.5) 已经拥有13个一级指令和近30个二级指令, 期间 goctl 做了一些调整,而且,gcotl 本身的前进步伐也非常快,他更像是在摸索中前进,朝着更快,更好用的方向发展,因此在迭代的路上,goctl 会显得有些不稳定,大家兴许也遇到很多问题,这里大概总结一下大家在社区中反馈比较多的一些问题来分享一下。

1. 386 架构上安装 goctl 失败!

描述:antlr 生成的源码中,没有对 386 架构的 uint 的边界值进行很好的处理,导致边界溢出

修复版本:v1.3.3

2. grpc 到底安装什么版本插件?

描述:熟悉 grpc 的人应该都知道,生成 grpc 代码的插件 protoc-gen-go 有两个仓库在维护,有3 个安装来源,2个维护仓库分别是:

# 1. golang
# github.com/golang/protobuf/protoc-gen-go
# 2. protocolbuffers
# github.com/protocolbuffers/protobuf-go/cmd/protoc-gen-go

三个安装来源是

# 1. golang 维护的仓库,目前已不推荐使用
# github.com/golang/protobuf/protoc-gen-go
# 2. protocolbuffers 维护的,目前推荐使用的
# github.com/protocolbuffers/protobuf-go/cmd/protoc-gen-go
# 3. goolge 安装,这其实和第二种安装的是一个二进制,他的源码就是protocolbuffers 维护的相同仓库
# google.golang.org/protobuf/cmd/protoc-gen-go

在 v.1.3.4前,如果使用 goctl rpc proto 生成 zrpc 代码则建议安装旧版本的插件,即 golang 维护的,因此该指令生成 zrpc 代码是 goctl 为了用户生成指令的简单,做了很厚的封装,但随之带来的问题就是难兼容,因此该指令已不推荐使用。

在v.1.3.4及以后,没有对 protoc-gen-go 做限制,用户可以自由选择不同的来源进行安装,但建议还是安装 protocolbuffer 维护的版本(官方文档已经替换为这个),而且必须要安装protoc-gen-grpc-go 插件,这样做的目的是跟着 grpc 官方走,不过用户不用有太大的心理负担,一下安装这么多依赖,很麻烦,goctl 都已经帮你实现了,你只要使用 goctl rpc protoc 生成代码时会自动检测依赖并安装。

综上所述,建议大家还在使用该指令的用户尽早用 goctl rpc protoc 替代。

3. 为什么 Windows 上生成 api/zrpc 代码时,总是提示 The system cannot find the path specified 类似错误?

goctl.exe api go -api test.api -dir .
Stat : The system cannot find the path specified.

描述:产生该原因是因为 go list -json -m 获取 go module 时拿到的是一个固定值command-line-arguments,该问题已经在 github.com/zeromicro/g… 进行修复,版本将在 v1.3.6 生效。

4. No help topic 'proto'

描述:该指令在 v1.3.4 已经移除,用 goctl rpc protoc 替代

5. zrpc 生成代码时报 go_package 错误

protoc-gen-go: unable to determine Go import path for "greet.proto"
Please specify either:
• a "go_package" option in the .proto source file, or
• a "M" argument on the command line.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#package for more information.
--go_out: protoc-gen-go: Plugin failed with status code 1.

6. zrpc 生成代码时指定了 pb 的输出目录为当前服务 main 目录

the output of pb.go and _grpc.pb.go must not be the same with --zrpc_out:
pb output: /Users/keson/workspace/awesome-goctl/zwesome-zrpc/pb_in_main
zrpc out: /Users/keson/workspace/awesome-goctl/zwesome-zrpc/pb_in_main

7. 为什么我的代码生成的 pb client(不)带 client 标志?

这是旧版本 goctl rpc proto 生成 zrpc 代码时才有这个问题,目前已经移除了该指令。

8. 为什么我生成的目录结构和文档演示不一样?

对于 goctl rpc protoc 生成 zrpc 代码的目录结构,总的结构上是不会存在差异的,唯一存在差异的是 pb 的输出目录,这个取决于你指定的参数来控制,控制 pb 输出目录的因素有 go_optgo-grpc_optgo_package ,详情可参考 《Protocol Buffers: Go Generated Code》。

9. 为什么我安装了 goctl 编辑器插件还是不能高亮

打开 Goland 的设置,搜索 FileTypes 设置 api 文件后缀即可。

项目地址 github.com/zeromicro/g…

以上就是微服务效率工具 goctl 深度解析的详细内容,更多关于微服务效率工具 goctl 深度解析的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go微服务项目配置文件的定义和读取示例详解

    目录 前言 场景 定义配置 配置文件 加载配置文件 实现原理 总结 项目地址 前言 我们在写应用时,基本都会用到配置文件,从各种 shell 到 nginx 等,都有自己的配置文件.虽然这没有太多难度,但是配置项一般相对比较繁杂,解析.校验也会比较麻烦.本文就给大家讲讲我们是怎么简化配置文件的定义和解析的. 场景 如果我们要写一个 Restful API 的服务,配置项大概有如下内容: Host,侦听的 IP,如果不填,默认用 0.0.0.0 Port,侦听的端口,必填,只能是数字,大于等于80

  • 详解Go语言微服务开发框架之Go chassis

    引言 https://github.com/go-chassis/go-chassis是一个微服务开发框架,而微服务开发框架带来的其中一个课题就是:当单体应用向微服务转型后,有大量的配置需要管理,而你并不希望登录到远端机器去更改配置,并重启应用,尤其是现在已经是容器的时代了,也不希望因为一个配置的变更,而发布一个新的软件包.那么分布式系统中每个进程的动态配置管理及运行时热加载就成为了一个亟待解决的问题.https://github.com/go-chassis/go-archaius为gocha

  • golang微服务框架基础Gin基本路由使用详解

    目录 概述 1. 基本路由 2. 路由参数 获取URL路径全部参数 获取URL路径单个参数 获取URL中指定的参数 获取指定默认值的参数的 概述 路由是自定义url地址执行指定的函数,良好的路由定义可以对seo起到很好的效果. 1. 基本路由 gin框架封装了http库,提供了 GET.POST.PUT.DELETE.PATCH.HEAD.OPTIONS 这些http请求方式. 使用 router.method() 来绑定路由 func (group *RouterGroup) METHOD(r

  • golang 微服务之gRPC与Protobuf的使用

    RPC是什么? 所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型.使用的时候客户端调用server端提供的接口就像是调用本地的函数一样. gRPC是什么? 与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型远程调用的方法.默认情况下,gRPC使用协议缓冲区作为接口定义语言(IDL)来描述服务接口和有效负载消息的结构. gRPC有什么好处以及在什么场景下

  • golang 实现一个restful微服务的操作

    如何用net/http构建一个简单的web服务 Golang提供了简洁的方法来构建web服务 package main import ( "net/http" ) func HelloResponse(rw http.ResponseWriter, request *http.Request) { fmt.Fprintf(w, "Hello world.") } func main() { http.HandleFunc("/", HelloRe

  • 微服务效率工具 goctl 深度解析

    目录 前言 goctl 的由来 1. goctl 的诞生 2. 为什么需要 goctl? 3. 怎么理解开发规范? 4. 怎么理解工程效率? 二 .goctl 的安装及功能介绍 1. 介绍 2. 安装 go get/install docker 3. 功能介绍 goctl completion 1.3.5 1.3.6 goctl migrate goctl env 1. 环境查看 2. 修改参数 3. 依赖检测/安装 goctl rpc 4. 编辑器插件 三.goctl 使用中遇到的问题 1.

  • Spring Cloud Stream微服务消息框架原理及实例解析

    随着近些年微服务在国内的盛行,消息驱动被提到的越来越多.主要原因是系统被拆分成多个模块后,一个业务往往需要在多个服务间相互调用,不管是采用HTTP还是RPC都是同步的,不可避免快等慢的情况发生,系统性能上很容易遇到瓶颈.在这样的背景下,将业务中实时性要求不是特别高且非主干的部分放到消息队列中是很好的选择,达到了异步解耦的效果. 目前消息队列有很多优秀的中间件,目前使用较多的主要有 RabbitMQ,Kafka,RocketMQ 等,这些中间件各有优势,有的对 AMQP(应用层标准高级消息队列协议

  • Springboot微服务打包Docker镜像流程解析

    1.构建springboot项目 2.打包应用 3.编写dockerfile 4.构建镜像 5.发布运行! [root@localhost demo]# ls demo02-0.0.1-SNAPSHOT.jar Dockerfile # Dockerfile文件 [root@localhost demo]# cat Dockerfile FROM java:8 COPY *.jar /app.jar CMD ["--server.port=8080"] EXPOSE 8080 ENTR

  • 解析SpringCloud简介与微服务架构

    1. 微服务架构 1.1 微服务架构理解 微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦.你可以将其看作是在架构层次而非获取服务的类上应用很多SOLID原则.微服务架构是个很有趣的概念,它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持. 概念:把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,它可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等

  • 详解多云架构下的JAVA微服务技术解析

    微服务生态 微服务生态本质上是一种微服务架构模式的实现,包括微服务开发SDK,以及微服务基础设施. 目前比较成熟的 JAVA 微服务生态包括 servicecomb(华为), spring-cloud (Pivotal), dubbo(阿里), tsf(腾讯)等.gRPC.Thrift 等也用于内部服务之间的通信,但是微服务基础设施比较欠缺. 核心的微服务基础设施包括:注册中心.配置中心.应用网关.此外,分布式事物管理.计划任务.调用链跟踪系统等也是微服务基础设施的组成部分.完整的微服务基础实施

  • SpringBoot+SpringCloud用户信息微服务传递实现解析

    这篇文章主要介绍了SpringBoot+SpringCloud实现登录用户信息在微服务之间的传递,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 实现思路: 1:准备一个ThreadLocal变量,供线程之间共享. 2:每个微服务对所有过来的Feign调用进行过滤,然后从请求头中获取User用户信息,并存在ThreadLocal变量中. 3:每个微服务在使用FeignClient调用别的微服务时,先从ThreadLocal里面取出user信息,并

  • spring boot微服务场景下apollo加载过程解析

    目录 集成使用 1.添加gradle依赖 2.配置application.properties 必须配置 可选配置 加载过程解析 postProcessEnvironment方法逻辑解析 initialize方法逻辑解析 结语 集成使用 1.添加 gradle 依赖 implementation "com.ctrip.framework.apollo:apollo-client:1.6.0" 2.配置 application.properties apollo 自身的配置共包含 9 项

  • SpringCloud基于RestTemplate微服务项目案例解析

    目录 基于RestTemplate微服务项目 一.构建父工程 二.构建serverspringcloud-api(公共子模块) 三.创建部门微服务提供者 四.创建部门微服务消费者 五.总结 基于RestTemplate微服务项目 在写SpringCloud搭建微服务之前,我想先搭建一个不通过springcloud只通过SpringBoot和Mybatis进行模块之间额通讯.然后在此基础上再添加SpringCloud框架. 下面先对案例做个说明 该项目有一个maven父模块,其中里面有三个子模块:

  • springcloud微服务基于redis集群的单点登录实现解析

    简介 本文介绍微服务架构中如何实现单点登录功能 创建三个服务: 操作redis集群的服务,用于多个服务之间共享数据 统一认证中心服务,用于整个系统的统一登录认证 服务消费者,用于测试单点登录 大体思路:每个服务都设置一个拦截器检查cookie中是否有token,若有token,则放行,若没有token,重定向到统一认证中心服务进行登录,登录成功后返回到被拦截的服务. 搭建redis集群服务 搭建redis集群参考文档 搭建统一认证中心 主函数添加注解 /** * 单点登录既要注册到服务注册中心,

  • Springcloud微服务架构基础知识解析

    一 前言 学习微服务要从基础的架构学起,首先你要有个微服务的概念才能学习对吧!!如果你都不知道啥是微服务,就一头扎进去学习,你自己也觉得自己也学不会对吧.本篇文章主要让大家快速了解基础的架构分格,以便于微服务入门. 二 单体架构 单体架构是传统架构,其发展了几十年,我们今天任然还在用单体架构开发,存在即合理:单体架构也就是通常的表现层跟UI界面交互,业务层写业务逻辑,数据DAO层访问数据库.其部署方式也很简单,直接将项目打包成war包放进web服务器(如tomcat,jetty)中运行: 其优点

随机推荐