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
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
进入到项目根目录(calculator根目录), 执行:
protoc -I .\protobuf --go_out=plugins=grpc:.\protobuf .\protobuf\calculator.proto
则会在calculator/protobuf目录下生成.pb.go文件
新建文件: 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 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
, 效果如下图:
上述示例可在这里下载.
https://grpc.io/docs/quickstart/go/
https://developers.google.com/protocol-buffers/docs/proto3