青训营笔记

105 阅读1分钟

Go中的GO-zero

这是我参与【第五届青训营】伴学笔记创作活动的第18天

1.安装goctl

方式一(go get# Go 1.15 及之前版本
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

#查看版本
goctl -v 

#查看api功能
goctl api -h

2.创建一个单体服务

  • 例如:创建一个greet服务
$ mkdir go-zero-demo
$ cd go-zero-demo
$ go mod init go-zero-demo
$ goctl api new greet
$ go mod tidy
Done.

我们可以看到生成的目录结构是:

$ tree greet
greet
├── etc
│   └── greet-api.yaml
├── greet.api
├── greet.go
└── internal
    ├── config
    │   └── config.go
    ├── handler
    │   ├── greethandler.go
    │   └── routes.go
    ├── logic
    │   └── greetlogic.go
    ├── svc
    │   └── servicecontext.go
    └── types
        └── types.go

3.微服务

  • 如未安装 protoc,protoc-gen-go,protoc-gen-grpc-go 你可以通过如下指令一键安装:
$ goctl env check -i -f

3.1 创建user rpc服务

#创建user rpc服务
$ mkdir -p mall/user/rpc


#添加`user.proto`文件,增加`getUser`方法
$ vim mall/user/rpc/user.proto

3.2 在创建的user.proto写入对应的代码

syntax = "proto3";

package user;
  
// protoc-gen-go 版本大于1.4.0, proto文件需要加上go_package,否则无法生成
option go_package = "./user";

message IdRequest {
    string id = 1;
}
  
message UserResponse {
    // 用户id
    string id = 1;
    // 用户名称
    string name = 2;
    // 用户性别
    string gender = 3;
}
  
service User {
    rpc getUser(IdRequest) returns(UserResponse);
}
  • 注意: 1、每一个 *.proto文件只允许有一个service error: only one service expected
  • 执行对应proto文件
#cd到对应的文件目录下面
$ cd mall/user/rpc

#执行此语句
$ goctl rpc protoc user.proto --go_out=./types --go-grpc_out=./types --zrpc_out=.
Done.

3.3 创建order api服务

# 回到 go-zero-demo/mall 目录

$ mkdir -p order/api 
$ cd order/api

3.4 编写order.api文件

  • 一开始golang是没有.api文件的,我们需要去插件下载Goctl就有.api文件可以生成
type(
    OrderReq {
        Id string `path:"id"`
    }
  
    OrderReply {
        Id string `json:"id"`
        Name string `json:"name"`
    }
)
service order {
    @handler getOrder
    get /api/order/get/:id (OrderReq) returns (OrderReply)
}

3.5 生成order服务

  • 先进入到对应的api目录中
$ goctl api go -api order.api -dir .
Done.

3.6 添加user rpc配置

  • vim internal/config/config.go
package config

import (

"github.com/zeromicro/go-zero/zrpc"

"github.com/zeromicro/go-zero/rest"

)

type Config struct {

rest.RestConf

UserRpc zrpc.RpcClientConf

}

3.7 添加yaml配置

  • $ vim etc/order.yaml
Name: order
Host: 0.0.0.0
Port: 8888
UserRpc:
  Etcd:
    Hosts:
    - 127.0.0.1:2379
    Key: user.rpc

3.8 完善服务依赖

  • $ vim internal/svc/servicecontext.go
package svc

type ServiceContext struct {
    Config  config.Config
    UserRpc userclient.User
}

func NewServiceContext(c config.Config) *ServiceContext {
    return &ServiceContext{
        Config:  c,
        UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),
    }
}

3.9 添加order演示逻辑,给getorderlogic添加业务逻辑

  • $ vim internal/logic/getorderlogic.go
func (l *GetOrderLogic) GetOrder(req *types.OrderReq) (resp *types.OrderReply, err error) {
	user, err := l.svcCtx.UserRpc.GetUser(l.ctx, &user.IdRequest{
		Id: "1",
	})
	if err != nil {
		return nil, err
	}

	if user.Name != "test" {
		return nil, errors.New("用户不存在")
	}

	return &types.OrderReply{
		Id:   req.Id,
		Name: "test order",
	}, nil
}

3.10 启动etcd,然后进入到项目目录下

  • 下载依赖
# 在 go-zero-demo 目录下
$ go mod tidy

3.11 启动user rpc

# 在 mall/user/rpc 目录
$ go run user.go -f etc/user.yaml
Starting rpc server at 127.0.0.1:8080...

3.12 启动order api

# 在 mall/order/api 目录
$ go run order.go -f etc/order.yaml
Starting server at 0.0.0.0:8888...

3.13 访问order api

$ curl -i -X GET http://localhost:8888/api/order/get/1
HTTP/1.1 200 OK
Content-Type: application/json
Date: Sun, 07 Feb 2021 03:45:05 GMT
Content-Length: 30

{"id":"1","name":"test order"}