Kratos tool doc (#51)

* add new project to kratos tool
* add kratos tool doc
pull/52/head
Felix Hao 6 years ago committed by GitHub
parent d8b83c5809
commit 436db51d86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      README.md
  2. BIN
      doc/img/kratosinit.gif
  3. 2
      doc/wiki-cn/blademaster-quickstart.md
  4. 112
      doc/wiki-cn/kratos-tool.md
  5. 15
      doc/wiki-cn/protoc.md
  6. 12
      doc/wiki-cn/quickstart.md
  7. 2
      doc/wiki-cn/summary.md
  8. 18
      doc/wiki-cn/warden-quickstart.md
  9. 29
      tool/kratos/build.go
  10. 27
      tool/kratos/doc.go
  11. 155
      tool/kratos/init.go
  12. 39
      tool/kratos/main.go
  13. 33
      tool/kratos/new.go
  14. 22
      tool/kratos/project.go
  15. 28
      tool/kratos/run.go
  16. 2
      tool/kratos/template.go
  17. 42
      tool/kratos/tool.go
  18. 6
      tool/kratos/tool_index.go

@ -18,7 +18,7 @@ Kratos是[bilibili](https://www.bilibili.com)开源的一套Go微服务框架,
* [log](doc/wiki-cn/logger.md):基于[zap](https://github.com/uber-go/zap)的field方式实现的高性能log库,集成了我们提供的[log-agent敬请期待]()日志收集方案。
* [database](doc/wiki-cn/database.md):集成MySQL&HBase&TiDB的SDK,其中TiDB使用服务发现方案。
* [cache](doc/wiki-cn/cache.md):集成memcache&redis的SDK,注意无redis-cluster实现,推荐使用代理模式[overlord](https://github.com/bilibili/overlord)。
* [kratos tool](doc/wiki-cn/kratos-tool.md):kratos相关工具量,包括项目快速生成、pb文件代码生成、swagger文档生成等。
* [kratos工具](doc/wiki-cn/kratos-tool.md):kratos相关工具量,包括项目快速生成、pb文件代码生成、swagger文档生成等。
我们致力于提供完整的微服务研发体验,整合相关框架及工具后,微服务治理相关部分可对整体业务开发周期无感,从而更加聚焦于业务交付。对每位开发者而言,整套Kratos框架也是不错的学习仓库,可以了解和参考到[bilibili](https://www.bilibili.com)在微服务方面的技术积累和经验。
@ -26,10 +26,11 @@ Kratos是[bilibili](https://www.bilibili.com)开源的一套Go微服务框架,
```shell
go get -u github.com/bilibili/kratos/tool/kratos
kratos init
cd $GOPATH/src
kratos new kratos-demo
```
`kratos init`会快速生成基于kratos库的脚手架代码,如生成[kratos-demo](https://github.com/bilibili/kratos-demo)
`kratos new kratos-demo`会快速生成基于kratos库的脚手架代码,如生成[kratos-demo](https://github.com/bilibili/kratos-demo)
```shell
cd kratos-demo/cmd
@ -39,9 +40,10 @@ go build
打开浏览器访问:[http://localhost:8000/kratos-demo/start](http://localhost:8000/kratos-demo/start),你会看到输出了`Golang 大法好 !!!`
[快速开始](doc/wiki-cn/quickstart.md)
[快速开始](doc/wiki-cn/quickstart.md)
[kratos工具](doc/wiki-cn/kratos-tool.md)
# Document
# 文档目录
[简体中文](doc/wiki-cn/summary.md)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

@ -1,6 +1,6 @@
# 准备工作
推荐使用[kratos tool](kratos-tool.md)快速生成项目,如我们生成一个叫`kratos-demo`的项目。
推荐使用[kratos工具](kratos-tool.md)快速生成项目,如我们生成一个叫`kratos-demo`的项目。
生成目录结构如下:
```

@ -0,0 +1,112 @@
# 介绍
kratos包含了一批好用的工具集,比如项目一键生成、基于proto生成http&grpc代码,生成缓存回源代码,生成memcache执行代码,生成swagger文档等。
# 获取工具
执行以下命令,即可快速安装好`kratos`工具
```shell
go get -u github.com/bilibili/kratos/tool/kratos
```
那么接下来让我们快速开始熟悉工具的用法~
# kratos本体
`kratos`是所有工具集的本体,就像`go`一样,拥有执行各种子工具的能力,如`go build`和`go tool`。先让我们看看`-h`的输出:
```
NAME:
kratos - kratos tool
USAGE:
kratos [global options] command [command options] [arguments...]
VERSION:
0.0.1
COMMANDS:
new, n create new project
build, b kratos build
run, r kratos run
tool, t kratos tool
version, v kratos version
self-upgrade kratos self-upgrade
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
```
可以看到`kratos`有如:`new` `build` `run` `tool`等在内的COMMANDS,那么接下来一一演示如何使用。
# kratos new
`kratos new`是快速创建一个项目的命令,执行如下:
```shell
kratos new kratos-demo
```
即可快速在当前目录生成一个叫`kratos-demo`的项目。此外还支持指定owner和path,如下:
```shell
kratos new kratos-demo -o YourName -d YourPath
```
注意,`kratos new`默认是不会生成`grpc`示例代码的,如需生成请加`--grpc`,如下:
```shell
kratos new kratos-demo -o YourName -d YourPath --grpc
```
特别注意,如果不是macos系统,生成的示例项目`api`目录下的`proto`文件并不会自动生成对应的`.pb.go`文件,需要参考以下说明进行生成。
[protoc说明](protoc.md)
# kratos build&run
`kratos build`和`kratos run`是`go build`和`go run`的封装,并无特别用途。
# kratos tool
`kratos tool`是基于proto生成http&grpc代码,生成缓存回源代码,生成memcache执行代码,生成swagger文档等工具集,先看下`kratos tool`的执行效果:
```
kratos(已安装): Kratos工具集本体 Author(kratos) [2019/04/02]
kprotoc(已安装): 快速方便生成pb.go的protoc封装,不支持Windows,Linux请先安装protoc工具 Author(kratos) [2019/04/02]
安装工具: kratos tool install demo
执行工具: kratos tool demo
安装全部工具: kratos tool install all
详细文档: https://github.com/bilibili/kratos/blob/master/doc/wiki-cn/kratos-tool.md
```
***小小说明:如未安装工具,第一次运行也可自动安装,不需要特别执行install***
目前已经集成的工具有:
* `kprotoc`用于快速生成`pb.go`文件,但目前不支持windows,Linux也需要先自己安装`protoc`工具。
* TODOs...
### kratos tool kprotoc
该命令运行没其他参数,直接`kratos tool kprotoc`运行即可。但使用前需特别说明:
* 该工具不支持Windows用户,请安装`protoc`和`gogo protobuf`工具
* 该工具在Linux下运行,需提前安装好`protoc`工具
该工具实际是一段`shell`脚本,其中自动将`protoc`命令进行了拼接,识别了需要`include`的目录和当前目录下的`proto`文件,最终会拼接为如下命令进行执行:
```shell
protoc -I/Users/felix/work/go/src:/usr/local/include --gogofast_out=plugins=grpc:/Users/felix/work/go/src /Users/felix/work/go/src/kratos-demo/api/api.proto
```
Windows和Linux用户可以参考该命令进行`proto`生成`pb.go`文件,也可以参考[protoc说明](protoc.md)。
### TODOs
-------------
[文档目录树](summary.md)

@ -0,0 +1,15 @@
# protoc
`protobuf`是Google官方出品的一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
使用`protobuf`,需要先书写`.proto`文件,然后编译该文件。编译`proto`文件则需要使用到官方的`protoc`工具,安装文档请参看:[google官方protoc工具](https://github.com/protocolbuffers/protobuf#protocol-compiler-installation)。
注意:`protoc`是用于编辑`proto`文件的工具,它并不具备生成对应语言代码的能力,所以正常都是`protoc`配合对应语言的代码生成工具来使用,如Go语言的[gogo protobuf](https://github.com/gogo/protobuf),请先点击按文档说明安装。
安装好对应工具后,我们可以进入`api`目录,执行如下命令:
```shell
protoc -I/Users/felix/work/go/src:/usr/local/include --gogofast_out=plugins=grpc:/Users/felix/work/go/src /Users/felix/work/go/src/kratos-demo/api/api.proto
```
请注意替换`/Users/felix/work/go/src`目录为你本地开发环境对应GOPATH目录,其中`--gogofast_out`意味着告诉`protoc`工具需要使用`gogo protobuf`的工具生成代码。

@ -1,18 +1,20 @@
# 快速开始
快速使用kratos项目,可以使用`kratos tool`,如下:
快速使用kratos项目,可以使用`kratos`工具,如下:
```shell
go get -u github.com/bilibili/kratos/tool/kratos
kratos init
cd $GOPATH/src
kratos new kratos-demo
```
根据提示可以快速创建项目,如[kratos-demo](https://github.com/bilibili/kratos-demo)就是通过工具创建生成。目录结构如下:
```
├── CHANGELOG.md # CHANGELOG
├── CONTRIBUTORS.md # CONTRIBUTORS
├── README.md # README
├── api # api目录为对外保留的proto文件及生成的pb.go文件
├── api # api目录为对外保留的proto文件及生成的pb.go文件,注:需要"--grpc"参数
   ├── api.proto
   ├── api.pb.go # 通过go generate生成的pb.go文件
   └── generate.go
@ -51,9 +53,7 @@ go build
打开浏览器访问:[http://localhost:8000/kratos-demo/start](http://localhost:8000/kratos-demo/start),你会看到输出了`Golang 大法好 !!!`
# 动图说明
![kratos init](/doc/img/kratosinit.gif)
[kratos工具](kratos-tool.md)
-------------

@ -24,4 +24,4 @@
* [cache](cache.md)
* [memcache](cache-mc.md)
* [redis](cache-redis.md)
* [kratos tool](kratos-tool.md)
* [kratos工具](kratos-tool.md)

@ -1,23 +1,29 @@
# 准备工作
推荐使用[kratos tool](kratos-tool.md)快速生成项目,如我们生成一个叫`kratos-demo`的项目。
[快速开始](quickstart.md)
推荐使用[kratos工具](kratos-tool.md)快速生成带`--grpc`的项目,如我们生成一个叫`kratos-demo`的项目。
# pb文件
创建项目成功后,进入`api`目录下可以看到`api.proto`和`api.pb.go`和`generate.go`文件,其中:
* `api.proto`是gRPC server的描述文件
* `api.pb.go`是基于`api.proto`生成的代码文件
* `generate.go`是用于`kratos tool`执行`go generate`进行代码生成的临时文件
* `generate.go`是用于`kratos tool kprotoc`执行`go generate`进行代码生成的临时文件
接下来可以将以上三个文件全部删除或者保留`generate.go`,之后编写自己的proto文件,确认proto无误后,进行代码生成:
* 可直接执行`kratos tool kprotoc`,该命令会调用protoc工具生成`.pb.go`文件
* 如`generate.go`没删除,也可以执行`go generate`命令,将调用`kratos tool kprotoc`工具进行代码生成
[kprotoc说明请看](kratos-tool.md)
### 如没看kprotoc文档,请看下面这段话
`kratos tool kprotoc`用于快速生成`pb.go`文件,但目前不支持windows,Linux也需要先自己安装`protoc`工具,具体请看[protoc说明](protoc.md)。
# 注册server
进入`internal/server/grpc`目录,打开`server.go`文件,可以看到以下代码,只需要替换以下注释内容就可以启动一个gRPC服务。
进入`internal/server/grpc`目录打开`server.go`文件,可以看到以下代码,只需要替换以下注释内容就可以启动一个gRPC服务。
```go
package grpc
@ -68,7 +74,7 @@ func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.
* 第一个返回值必须是proto内定义的`message`对应生成的结构体,第二个参数必须是`error`
* 在http框架bm中,如果共用proto文件生成bm代码,那么也可以直接使用该service方法
建议service严格按照此格式声明方法使其能够在bm和warden内共用
建议service严格按照此格式声明方法使其能够在bm和warden内共用
# client调用

@ -1,18 +1,47 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"github.com/urfave/cli"
)
func buildAction(c *cli.Context) error {
base, err := os.Getwd()
if err != nil {
panic(err)
}
args := append([]string{"build"}, c.Args()...)
cmd := exec.Command("go", args...)
cmd.Dir = buildDir(base, "cmd", 5)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
fmt.Printf("directory: %s\n", cmd.Dir)
fmt.Printf("kratos: %s\n", Version)
if err := cmd.Run(); err != nil {
panic(err)
}
fmt.Println("build success.")
return nil
}
func buildDir(base string, cmd string, n int) string {
dirs, err := ioutil.ReadDir(base)
if err != nil {
panic(err)
}
for _, d := range dirs {
if d.IsDir() && d.Name() == cmd {
return path.Join(base, cmd)
}
}
if n <= 1 {
return base
}
return buildDir(filepath.Dir(base), cmd, n-1)
}

@ -1,27 +0,0 @@
/*
kratos 是Kratos的工具链提供新项目创建代码生成等功能
kartos build 本目录之下局部编译根目录全量编译
NAME:
kratos build
USAGE:
kratos build [arguments...]
EXAMPLE:
cd app && kratos build ./service/.. admin interface/.. tool/cache/...
kratos build
kartos init 新建新项目
USAGE:
kratos init [command options] [arguments...]
OPTIONS:
-n value 项目名
-o value 维护人
--grpc 是否是GRPC
EXAMPLE:
kratos init -n demo -o kratos
*/
package main

@ -1,155 +0,0 @@
package main
import (
"fmt"
"go/build"
"os"
"path/filepath"
"strings"
"github.com/urfave/cli"
"gopkg.in/AlecAivazis/survey.v1"
)
const (
_textModeFastInit = "一键初始化项目"
_textModeInteraction = "自定义项目参数"
_textYes = "是"
_textNo = "否"
)
func runInit(ctx *cli.Context) (err error) {
if ctx.NumFlags() == 0 {
if err = interact(); err != nil {
return
}
}
if !validate() {
return nil
}
if err = create(); err != nil {
fmt.Println("项目初始化失败: ", err.Error())
return nil
}
fmt.Printf("项目[%s]初始化成功!\n", p.Path)
return nil
}
func initPwd() (ok bool) {
pwd, err := os.Getwd()
if err != nil {
return
}
ps := strings.Split(pwd, string(os.PathSeparator))
plen := len(ps)
if plen < 1 {
// 至少要有一个目录层级:项目名
return
}
name := ps[plen-1]
if name == "" {
return
}
p.Name = name
p.Path = pwd
return true
}
func goPath() (gp string) {
gopaths := strings.Split(os.Getenv("GOPATH"), ":")
if len(gopaths) == 1 {
return gopaths[0]
}
pwd, err := os.Getwd()
if err != nil {
return
}
abspwd, err := filepath.Abs(pwd)
if err != nil {
return
}
for _, gopath := range gopaths {
absgp, err := filepath.Abs(gopath)
if err != nil {
return
}
if strings.HasPrefix(abspwd, absgp) {
return absgp
}
}
return build.Default.GOPATH
}
func interact() (err error) {
qs1 := &survey.Select{
Message: "你想怎么玩?",
Options: []string{_textModeFastInit, _textModeInteraction},
}
var ans1 string
if err = survey.AskOne(qs1, &ans1, nil); err != nil {
return
}
switch ans1 {
case _textModeFastInit:
if ok := initPwd(); !ok {
fmt.Println("快速初始化失败!")
}
return
case _textModeInteraction:
// go on
default:
return
}
qs := []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "请输入项目名称:",
},
Validate: survey.Required,
},
{
Name: "owner",
Prompt: &survey.Input{
Message: "请输入项目负责人:",
},
},
{
Name: "useGRPC",
Prompt: &survey.Select{
Message: "是否使用 gRPC ?",
Options: []string{_textYes, _textNo},
Default: _textNo,
},
},
{
Name: "here",
Prompt: &survey.Select{
Message: "是否当前目录?默认为GOPATH下",
Options: []string{_textYes, _textNo},
Default: _textYes,
},
},
}
ans := struct {
Name string
Owner string
UseGRPC string
Here string
}{}
if err = survey.Ask(qs, &ans); err != nil {
return
}
p.Name = ans.Name
p.Owner = ans.Owner
if ans.UseGRPC == _textYes {
p.WithGRPC = true
}
if ans.UseGRPC == _textYes {
p.WithGRPC = true
}
if ans.Here == _textYes {
p.Here = true
}
return
}

@ -10,40 +10,47 @@ import (
func main() {
app := cli.NewApp()
app.Name = "kratos"
app.Usage = "kratos tool"
app.Usage = "kratos工具集"
app.Version = Version
app.Commands = []cli.Command{
{
Name: "build",
Aliases: []string{"b"},
Usage: "kratos build",
Action: buildAction,
},
{
Name: "init",
Aliases: []string{"i"},
Name: "new",
Aliases: []string{"n"},
Usage: "create new project",
Flags: []cli.Flag{
cli.StringFlag{
Name: "n",
Value: "",
Usage: "project name for create project",
Destination: &p.Name,
},
cli.StringFlag{
Name: "o",
Value: "",
Usage: "project owner for create project",
Destination: &p.Owner,
},
cli.StringFlag{
Name: "d",
Value: "",
Usage: "project directory for create project",
Destination: &p.Path,
},
cli.BoolFlag{
Name: "grpc",
Usage: "whether to use grpc for create project",
Destination: &p.WithGRPC,
},
},
Action: runInit,
Action: runNew,
},
{
Name: "build",
Aliases: []string{"b"},
Usage: "kratos build",
Action: buildAction,
},
{
Name: "run",
Aliases: []string{"r"},
Usage: "kratos run",
Action: runAction,
},
{
Name: "tool",
Aliases: []string{"t"},

@ -0,0 +1,33 @@
package main
import (
"errors"
"fmt"
"os"
"path"
"github.com/urfave/cli"
)
func runNew(ctx *cli.Context) error {
if len(ctx.Args()) == 0 {
return errors.New("required project name")
}
p.Name = ctx.Args()[0]
if p.Path != "" {
p.Path = path.Join(p.Path, p.Name)
} else {
pwd, _ := os.Getwd()
p.Path = path.Join(pwd, p.Name)
}
// creata a project
if err := create(); err != nil {
return err
}
fmt.Printf("Project: %s\n", p.Name)
fmt.Printf("Owner: %s\n", p.Owner)
fmt.Printf("WithGRPC: %t\n", p.WithGRPC)
fmt.Printf("Directory: %s\n\n", p.Path)
fmt.Println("The application has been created.")
return nil
}

@ -6,7 +6,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"path"
"runtime"
"strings"
"text/template"
)
@ -84,22 +84,6 @@ var (
}
)
func validate() (ok bool) {
if p.Name == "" {
fmt.Println("[-n] Invalid project name.")
return
}
if p.Path == "" {
if p.Here {
pwd, _ := os.Getwd()
p.Path = path.Join(pwd, p.Name)
} else {
p.Path = path.Join(goPath(), "src", p.Name)
}
}
return true
}
func create() (err error) {
if p.WithGRPC {
files[_tplTypeGRPCServer] = "/internal/server/grpc/server.go"
@ -131,6 +115,10 @@ func create() (err error) {
if err = genpb(); err != nil {
return
}
if runtime.GOOS != "darwin" {
fmt.Println("您的操作系统不是macos,kprotoc工具无法正常运行,请参看kratos tool文档!")
fmt.Println("地址:", toolDoc)
}
}
return
}

@ -0,0 +1,28 @@
package main
import (
"os"
"os/exec"
"path"
"path/filepath"
"github.com/urfave/cli"
)
func runAction(c *cli.Context) error {
base, err := os.Getwd()
if err != nil {
panic(err)
}
dir := buildDir(base, "cmd", 5)
conf := path.Join(filepath.Dir(dir), "configs")
args := append([]string{"run", "main.go", "-conf", conf}, c.Args()...)
cmd := exec.Command("go", args...)
cmd.Dir = dir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
return nil
}

@ -433,7 +433,7 @@ replace (
cloud.google.com/go => github.com/googleapis/google-cloud-go v0.26.0
golang.org/x/crypto => github.com/golang/crypto v0.0.0-20190123085648-057139ce5d2b
golang.org/x/lint => github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3
golang.org/x/net => github.com/golang/net v0.0.0-20190311183353-d8887717615a
golang.org/x/net => github.com/golang/net v0.0.0-20190420063019-afa5a82059c6
golang.org/x/oauth2 => github.com/golang/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sync => github.com/golang/sync v0.0.0-20181108010431-42b317875d0f
golang.org/x/sys => github.com/golang/sys v0.0.0-20180905080454-ebe1bf3edb33

@ -2,6 +2,7 @@ package main
import (
"fmt"
"go/build"
"os"
"os/exec"
"path"
@ -15,16 +16,21 @@ import (
"github.com/urfave/cli"
)
const (
toolDoc = "https://github.com/bilibili/kratos/blob/master/doc/wiki-cn/kratos-tool.md"
)
func toolAction(c *cli.Context) (err error) {
if c.NArg() == 0 {
sort.Slice(toolIndexs, func(i, j int) bool { return toolIndexs[i].BuildTime.After(toolIndexs[j].BuildTime) })
for _, t := range toolIndexs {
updateTime := t.BuildTime.Format("2006/01/02")
fmt.Printf("%s%s: %s %s (%s) [%s]\n", color.HiMagentaString(t.Name), getNotice(t), color.HiCyanString(t.Summary), t.URL, t.Author, updateTime)
fmt.Printf("%s%s: %s Author(%s) [%s]\n", color.HiMagentaString(t.Name), getNotice(t), color.HiCyanString(t.Summary), t.Author, updateTime)
}
fmt.Println("\n执行 install 安装程序 如: kratos tool install demo")
fmt.Println("执行 工具名称 运行程序 如: kratos tool demo")
fmt.Println("\n安装全部工具: kratos tool install all")
fmt.Println("\n安装工具: kratos tool install demo")
fmt.Println("执行工具: kratos tool demo")
fmt.Println("安装全部工具: kratos tool install all")
fmt.Println("\n详细文档:", toolDoc)
return
}
if c.Args().First() == "install" {
@ -129,7 +135,6 @@ type Tool struct {
Summary string `json:"summary"`
Platform []string `json:"platform"`
Author string `json:"author"`
URL string `json:"url"`
}
func (t Tool) supportOS() bool {
@ -143,7 +148,7 @@ func (t Tool) supportOS() bool {
func (t Tool) install() {
if t.Install == "" {
fmt.Fprintf(os.Stderr, color.RedString("%s: 自动安装失败 详情请查看文档 %s\n", t.Name, t.URL))
fmt.Fprintf(os.Stderr, color.RedString("%s: 自动安装失败详情请查看文档:%s\n", t.Name, toolDoc))
return
}
cmds := strings.Split(t.Install, " ")
@ -174,3 +179,28 @@ func (t Tool) installed() bool {
_, err := os.Stat(t.toolPath())
return err == nil
}
func goPath() (gp string) {
gopaths := strings.Split(os.Getenv("GOPATH"), ":")
if len(gopaths) == 1 {
return gopaths[0]
}
pwd, err := os.Getwd()
if err != nil {
return
}
abspwd, err := filepath.Abs(pwd)
if err != nil {
return
}
for _, gopath := range gopaths {
absgp, err := filepath.Abs(gopath)
if err != nil {
return
}
if strings.HasPrefix(abspwd, absgp) {
return absgp
}
}
return build.Default.GOPATH
}

@ -10,15 +10,13 @@ var toolIndexs = []*Tool{
Summary: "Kratos工具集本体",
Platform: []string{"darwin", "linux", "windows"},
Author: "kratos",
URL: "wiki",
},
&Tool{
Name: "kprotoc",
BuildTime: time.Date(2019, 4, 2, 0, 0, 0, 0, time.Local),
Install: "bash -c ${GOPATH}/src/github.com/bilibili/kratos/tool/kprotoc/install_kprotoc.sh",
Summary: "快速方便生成pb.go的protoc封装",
Summary: "快速方便生成pb.go的protoc封装,不支持windows,Linux请先安装protoc工具",
Platform: []string{"darwin", "linux"},
Author: "kratos",
URL: "wiki",
Author: "https://github.com/tomwei7",
},
}

Loading…
Cancel
Save