golang之grpc入门

环境

  • go版本要求: go 1.6及以上

    C:\> go version
    go version go1.12 windows/amd64
    
  • 设置goproxy及go mod开启(win cmd)

    set GOPROXY=https://goproxy.io
    set GO111MODULE=on
    
  • 安装protoc编译工具(protobuf转成相应语言代码的工具)
    下载: https://github.com/protocolbuffers/protobuf/releases/download/v3.9.1/protoc-3.9.1-win64.zip
    并配置protoc到PATH环境变量
    验证protoc是否安装成功:

    C:\>protoc --version
    libprotoc 3.9.1
    
  • 相关sdk下载

    go get -u google.golang.org/grpc
    go get -u github.com/golang/protobuf/protoc-gen-go # protoc生成go语言的插件
    

简单示例

我们以一个"计算器"的例子来入门grpc在go语言中的使用:
示例项目(calculator)结构如下:

D:\workspace\test\grpc\calculator
│  go.mod
│  go.sum
│
├─client
│      client.go
│
├─protobuf
│      calculator.pb.go
│      calculator.proto
│
└─server
        server.go

定义service(calculator.proto)

syntax = "proto3"; // 使用protobuf版本3

option go_package = "protobuf"; // 这个影响生成的目录及go的package命名

// 定义一个计算服务, 输入为CalcRequest, 输出为CalcResponse
service CalculatorService {
	rpc calc(CalcRequest) returns (CalcResponse) {};
}

// 计算两个数某种运算(如加法)的参数
message CalcRequest {
	double a = 1;
	double b = 2;
	string op = 3;
}

// 计算结果
message CalcResponse {
	double r = 1;
}

// cd path/to/calculator
// protoc -I .\protobuf --go_out=plugins=grpc:.\protobuf .\protobuf\calculator.proto

生成.pb.go文件

进入到项目根目录(calculator根目录), 执行:

protoc -I .\protobuf --go_out=plugins=grpc:.\protobuf .\protobuf\calculator.proto

则会在calculator/protobuf目录下生成.pb.go文件

实现rpc service

新建文件: calculator/server/server.go, 内容如下:

package main

import (
	"calculator/protobuf"
	"context"
	"fmt"
	"google.golang.org/grpc"
	"net"
)

// 实现: CalculatorServiceServer接口, 在calculator.pb.go中定义
type server struct {}

func (server) Calc(ctx context.Context, req *protobuf.CalcRequest) (resp *protobuf.CalcResponse, err error) {
	a := req.GetA()
	b := req.GetB()
	op := req.GetOp()
	resp = &protobuf.CalcResponse{}

	switch op {
	case "+":
		resp.R = a + b
	case "-":
		resp.R = a - b
	case "*":
		resp.R = a * b
	case "/":
		if b == 0 {
			err = fmt.Errorf("divided by zero")
			return
		}
		resp.R = a / b
	}
	return
}

// 启动rpc server
func main() {
	listener, err := net.Listen("tcp", "localhost:3233")
	if err != nil {
		panic(err)
	}

	s := grpc.NewServer()
	protobuf.RegisterCalculatorServiceServer(s, &server{})
	fmt.Println("server start")
	err = s.Serve(listener)
	if err != nil {
		panic(err)
	}
}

生成go.mod

进到项目根目录执行:

go mod init calculator
go mod tidy

客户端调用示例

新建文件: calculator/client/client.go, 内容如下:

package main

import (
	"calculator/protobuf"
	"context"
	"fmt"
	"google.golang.org/grpc"
	"log"
)

func main() {
	// 连上grpc server
	conn, err := grpc.Dial("localhost:3233", grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}

	defer conn.Close()

	c := protobuf.NewCalculatorServiceClient(conn)
	
	// 调用远程方法
	resp, err := c.Calc(context.Background(), &protobuf.CalcRequest{
		A:  1,
		B:  2,
		Op: "+",
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(resp.GetR()) // 3

	resp, err = c.Calc(context.Background(), &protobuf.CalcRequest{
		A:  1,
		B:  0,
		Op: "/",
	})
	if err != nil { // 如果有error, 说明此次调用不成功, 作相应处理
		fmt.Println(err) // rpc error: code = Unknown desc = divided by zero
		return
	}
	fmt.Println(resp.GetR())
}

运行结果

开两个cmd窗口, 一个进到server目录, 执行go run server.go来启动rpc服务.
一个进到client目录, 执行go run client.go, 效果如下图:
server_client

资源下载

上述示例可在这里下载.

参考

https://grpc.io/docs/quickstart/go/
https://developers.google.com/protocol-buffers/docs/proto3

发布了231 篇原创文章 · 获赞 77 · 访问量 52万+

猜你喜欢

转载自blog.csdn.net/butterfly5211314/article/details/100914262