1.新建项目
practice
│ ├─go.mod
│ │ ├─go.sum
│ ├─api
│ │ ├─api.proto
│ │ └─pb
│ │ └─api.pb.go
│ │ └─api_grpc.pb.go
│ ├─client
│ │ ├─client.go
│ └─server
│ ├─server.go
2、项目初始化
$ cd practice
$ go mod init
3.定义一个proto例子api.proto
syntax = "proto3";
package api;
service ProductInfo {
// 添加商品
rpc addProduct(Product) returns (ProductId);
// 获取商品
rpc getProduct(ProductId) returns (Product);
}
message Product {
string id = 1;
string name = 2;
string description = 3;
}
message ProductId {
string value = 1;
}
4.编译proto文件,生成go代码
$ cd api
$ protoc --go_out=. --go-grpc_out=. api.proto
会生成两个文件,将这两个文件移动到 practice/api/pb目录下
practice
│ ├─api
│ │ ├─api.proto
│ │ └─pb
│ │ └─api.pb.go
│ │ └─api_grpc.pb.go
5、客户端程序代码如下 client.go
package main
import (
"context"
"flag"
"google.golang.org/grpc"
"log"
pb "practice/api/pb"
"time"
)
const (
defaultId = "1"
)
var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
id = flag.String("id", defaultId, "product to greet")
)
// 此方法仅以获取商品举例说明 getProduct()
func main() {
flag.Parse()
// 建立连接
conn, err := grpc.Dial(*addr, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
// 实例化client
c := pb.NewProductInfoClient(conn)
// 调用rpc,等待同步响应
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// 1、客户端函数调用,返回商品信息Product
r, err := c.GetProduct(ctx, &pb.ProductId{Id: *id})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
// 打印商品信息
log.Printf("Id: %s", r.GetId())
log.Printf("Name: %s", r.GetName())
log.Printf("Description: %s", r.GetDescription())
}
6、服务端程序代码如下 server.go
package main
import (
"context"
"flag"
"fmt"
"google.golang.org/grpc"
"log"
"net"
pb "practice/api/pb"
)
var (
port = flag.Int("port", 50051, "The server port")
)
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedProductInfoServer
}
// 2、服务端函数定义(客户端传进来Id)
func (s *server) GetProduct(ctx context.Context, in *pb.ProductId) (*pb.Product, error) {
return &pb.Product{Id: in.Id, Name: "巧克力", Description: "俄罗斯黑巧克力100%浓度"}, nil
}
func main() {
flag.Parse()
// 监听端口
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 实例化server
s := grpc.NewServer()
pb.RegisterProductInfoServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
7、运行
启动服务端
$ go run server.go
2022/06/08 17:06:12 server listening at 127.0.0.1:50051
启动客户端
$ go run client.go
2022/06/08 17:06:17 Id: 1
2022/06/08 17:06:17 Name: 巧克力
2022/06/08 17:06:17 Description: 俄罗斯黑巧克力100%浓度
8、完成
项目源代码:点击下载