01简介在前面两篇文章中,我们介绍了使用gRPC创建RPC应用的初步知识。我们了解到gRPC支持多种语言。在本文中,我们将介绍如何在Golang语言中使用gRPC。02准备既然要介绍Golang语言中gRPC的使用方法,那么就要搭建Golang开发环境。这部分内容比较简单,本文不再赘述。如果有读者对这部分内容不清楚,建议阅读Golang官网文档。另外,我们还需要安装界面设计语言Protocolbuffer的编译器protoc。我们在之前的文章《Protobuf——一种更小、更快、更简单的交互式数据语言》中也介绍了protoc的安装方法。本文就不再赘述,有需要了解的读者可以阅读本文。最后介绍一下protoc编译生成pb文件的插件protoc-gen-go和protoc-gen-go-grpc。插件安装方法如下:执行goinstall命令安装插件goinstallgoogle.golang.org/protobuf/cmd/protoc-gen-go@v1.26goinstallgoogle.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1修改PATH$exportPATH="$PATH:$(goenvGOPATH)/bin"完成以上两步后,我们就可以使用protoc编译.proto文件,生成pb文件了。03编写.proto文件并生成pb文件在Golang语言中使用gRPC,先编写.proto文件,然后使用protoc编译.proto文件生成pb文件,最后编写剩下的Golang代码。接口设计语言protobuf在之前的文章《Golang语言gRPC使用的接口设计语言protobuf》中也有介绍过。本文不再赘述。如果有读者需要了解,可以阅读本文。示例代码:编写.proto文件。syntax="proto3";optiongo_package="advanced_go/lesson06/proto/greeter";serviceGreeter{rpcSayHello(HelloRequest)returns(HelloReply){}}messageHelloRequest{stringname=1;}messageHelloReply{stringmessage=1;}编译protoc.proto文件生成pb文件。$protoc--go_out=.--go_opt=paths=source_relative\--go-grpc_out=.--go-grpc_opt=paths=source_relative\proto/helloworld.proto04在我们之前的文章什么是gRPC中编写服务端和客户端的Golang代码中介绍过,接下来我们通过示例代码介绍如何在Golang语言中使用gRPC。本文首先介绍使用gRPC的编码过程。限于篇幅,gRPC的更多使用方法将在后续文章介绍中公开。首先使用界面设计语言protobuf的protoc、protoc-gen-go和protoc-gen-go-grpc插件生成pb文件。通过查看生成的pb文件,可以看到protoc自动生成了结构体、接口、方法等Golang代码。接下来,我们只需要编写剩下的Golang代码即可。具体实现如下:服务端示例代码:const(port=":50051")typeserverstruct{pb.UnimplementedGreeterServer}func(s*server)SayHello(ctxcontext.Context,in*pb.HelloRequest)(*pb.HelloReply,error){log.Printf("Received:%v",in.GetName())return&pb.HelloReply{Message:"Hello"+in.GetName()},nil}funcmain(){lis,err:=net.Listen("tcp",port)iferr!=nil{log.Fatalf("failedtolisten:%v",err)}s:=grpc.NewServer()pb.RegisterGreeterServer(s,&server{})log.Printf("serverlisteningat%v",lis.Addr())iferr:=s.Serve(lis);err!=nil{log.Fatalf("failedtoserve:%v",err)}}看了上面的代码,我们使用Golang语言编写SayHello方法,其实就是自动生成的SayHello方法在pb文件中的具体实现,对应自动生成的pb文件helloworld_grpc.pb.go代码如下://UnimplementedGreeterServermustbeembeddedtohaveforwardcompatibleimplements.typeUnimplementedGreeterServerstruct{}func(UnimplementedGreeterServer)SayHello(context.Context,*HelloRequest)(*HelloReply,error){returnnil,status.Errorf(codes.Unimplemented,"methodSayHellonotimplemented")}在main函数中,我们使用grpc调用NewServer函数创建服务,然后使用pb文件中的RegisterGreeterServer函数注册服务,对应自动生成pb文件helloworld_grpc.pb。go中代码如下:funcRegisterGreeterServer(sgrpc.ServiceRegistrar,srvGreeterServer){s.RegisterService(&Greeter_ServiceDesc,srv)}客户端示例代码:const(address=":50051"defaultName="word")funcmain(){conn,err:=grpc.Dial(address,grpc.WithInsecure(),grpc.WithBlock())iferr!=nil{log.Fatalf("didnotconnect:%v",err)}deferconn.Close()c:=pb。NewGreeterClient(conn)name:=defaultNameiflen(os.Args)>1{name=os.Args[1]}ctx,cancel:=context.WithTimeout(context.Background(),time.Second)defercancel()r,err:=c.SayHello(ctx,&pb.HelloRequest{Name:name})iferr!=nil{log.Fatalf("couldnotgreet:%v",err)}log.Printf("Greeting:%s",r.GetMessage())}阅读以上代码,我们使用pb文件中的NewGreeterClient方法创建客户端,然后使用创建的客户端直接调用服务端的SayHello方法,对应自动生成的pb文件helloworld_grpc.pb.go中的代码如下:){return&greeterClient{cc}}func(c*greeterClient)SayHello(ctxcontext.Context,in*HelloRequest,opts...grpc.CallOption)(*HelloReply,error){out:=new(HelloReply)err:=c.cc.Invoke(ctx,"/Greeter/SayHello",in,out,opts...)iferr!=nil{returnil,err}returnout,nil}服务端和客户端代码写完后,我们分别启动服务Client和客户端,执行结果如下:gorungrpc_server/main.go2021/09/1123:02:59serverlisteningat[::]:500512021/09/1123:03:23Received:word2021/09/1123:03:31Received:frankgorungrpc_client/main.go2021/09/1123:03:23Greeting:Hellowordgorungrpc_client/main.gofrank2021/09/1123:03:31Greeting:Hellofrank05总结本文介绍如何在Golang语言中使用gRPC。为了方便广大读者朋友,本文以一个简单的例子从零到一的实现,介绍了使用Golang语言编写gRPC的编码过程。推荐读者朋友阅读本文并敲击示例代码,进一步加深理解。限于篇幅,我们会在后续文章中介绍更多gRPC的使用方式。编码过程总结如下:搭建Golang开发环境。安装protobuf编译器protoc和插件protoc-gen-go、protoc-gen-go-grpc,并设置环境变量。初始化项目gomodinit。编写protobuf,生成pb文件,执行gomodtidy整理依赖包。编写其余的Golang代码。
