grpc可以实现远程调用,比如实现一个go程序远程调用python程序。这不是闲着蛋疼吗?直接全部用go或者全部用python来写不用吗?确实如此,但是假如在这样的一个场景中,我们的项目有多个不同的功能,根据功能的不同拆分成了几个微服务,不同的功能完全分离开来,这样的话大大降低了代码的耦合度。
grpc官网链接
到github下载protoc用于编译proto文件 ==> 下载链接
然后在将下载完毕后的bin目录配置到环境变量中
3.安装需要的包:
go install google.golang.org/protobuf/cmd/[email protected]
go install google.golang.org/grpc/cmd/[email protected]
这里有个坑:安装的时候需要将go env中的GOOS设置为windows(使用go env -w GOOS=windows),否则GOPATH/bin下不会有如下的两个.exe文件
syntax = "proto3";
//踩坑:这里的包名一定要和服务端的包名一致
package test
//.表示生成go文件的存放位置 proto表示生成的go文件所属的包,可以任意
option go_package = ".;proto";
// 定义一个服务
service Greeter {
// 定义一个方法,接受HelloRequest消息并返回HelloReply消息
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
根据编写的proto文件使用命令生成两个go文件用于后续的操作
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative hello.proto
go_out:.pb指定输出文件路径
go_opt:.pb指定参数,比如--go_opt=paths=source_relative就是表明生成文件输出使用相对路径。
另一个同理用于指定_grpc.pb的
hello.proto指定生成的文件名
这两个文件是proto自动生成的go语言代码,接下来我们只需要基于生成的这两个文件进行编写即可。
服务端
package main
import (
"context"
"google.golang.org/grpc"
"net"
"test/proto"
)
type server struct {
/*
踩坑:服务定义的方法实际由UnimplementedGreeterServer实现
而原来的GreeterServer中新增了一个mustEmbedUnimplementedGreeterServer,这是不允许导出的私有变量
*/
*proto.UnimplementedGreeterServer
}
func (s *server) SayHelloAgain(ctx context.Context, in *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
func (s *server) SayHello(ctx context.Context, in *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
g := grpc.NewServer()
proto.RegisterGreeterServer(g, &server{})
listen, err := net.Listen("tcp", ":8002")
if err != nil {
panic("failed to listen:" + err.Error())
}
err = g.Serve(listen)
if err != nil {
panic("failed to start grpc:" + err.Error())
}
}
客户端
package main
import (
"context"
"fmt"
"google.golang.org/grpc"
"test/proto"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:8002", grpc.WithInsecure())
if err != nil {
panic("conn fail" + err.Error())
}
c := proto.NewGreeterClient(conn)
r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: "小番茄"})
if err != nil {
panic(err)
}
fmt.Println(r.Message)
}
如果要调用其它服务就改一下端口号就行了。
报错信息:
1.
解决:
修改包名:
https://github.com/techschool/pcbook-go/issues/3
2.找不到protoc命令
需要添加go/binGOPATH中。