跨语言调用
借助 PRC,比如 gPRC 技术,可以实现 Rust 和包括 Go 在内的其它语言进行跨语言调用。Rust 开发 gRPC 服务端和客户端
本章将使用 rust 来开发 gPRC 服务端和客户端Go 开发 gRPC 服务端和客户端
本章讨论 Go 开发 gRPC 服务端和客户端
Go 开发 gRPC 服务端和客户端
Go 开发 gRPC 需要两个protoc
插件和一个代码依赖。
- 插件:
protoc-gen-go
:用于将 proto 生成 Go 语言的数据结构 - 插件:
protoc-gen-go-grpc
:用于生成 gRPC 相关的代码 - 代码依赖:
google.golang.org/grpc
安装插件
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
生成代码
mkdir -p ./pb && \
protoc --go_out=./pb --go_opt=paths=source_relative \
--go-grpc_out=./pb --go-grpc_opt=paths=source_relative \
--proto_path=../proto helloworld.proto
由于本项目结构特殊,所以采用了特定的生成命令。更常用的命令参数,可供参考:
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ pb/helloworld.proto
由于本项目结构特殊,所以采用了特定的生成命令。更常用的命令参数,可供参考:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
pb/helloworld.proto
安装依赖
你可以手动安装依赖:
go get -u google.golang.org/grpc
更推荐的是,使用 go mod
来自动管理依赖:
服务端
在 server/main.go
中编写服务端代码。
首先,实现自己的 MyGreeter
服务:
type MyGreeter struct {
pb.UnimplementedGreeterServer
}
func (s *MyGreeter) SayHello(c context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "[Go] Hello " + in.Name}, nil
}
func main() {
addr := ":9527"
listen, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal("Error listening", err)
return
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &MyGreeter{})
log.Println("[GO] Server listen at:", addr)
if err := s.Serve(listen); err != nil {
log.Fatal("Error Serveing", err)
return
}
}
package main
import (
"context"
"helloworld_go/pb"
"log"
"net"
"google.golang.org/grpc"
)
type MyGreeter struct {
pb.UnimplementedGreeterServer
}
func (s *MyGreeter) SayHello(c context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "[Go] Hello " + in.Name}, nil
}
func main() {
addr := ":9527"
listen, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal("Error listening", err)
return
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &MyGreeter{})
log.Println("[GO] Server listen at:", addr)
if err := s.Serve(listen); err != nil {
log.Fatal("Error Serveing", err)
return
}
}
客户端
打开 client/go
来编写客户端代码:
package main
import (
"context"
"helloworld_go/pb"
"log"
"os"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func main() {
grpc_server_addr := os.Getenv("GRPC_SERVER")
if grpc_server_addr == "" {
grpc_server_addr = "127.0.0.1:9527"
}
conn, err := grpc.Dial(grpc_server_addr, grpc.WithTransportCredentials(insecure.NewCredentials())) // 本地测试没有 TLS, 禁用 TLS
if err != nil {
log.Fatal("Dial error: ", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "张三"})
if err != nil {
log.Fatal("SayHello error: ", err)
}
log.Println("Greeting:", r.GetMessage())
}
同样的,为了连接不同的服务端,我们的客户端通过环境变量 GRPC_SERVER
来指定服务端地址。
启动客户端:
go run client/main.go
指定环境变量来启动客户端:
GRPC_SERVER=127.0.0.1:9527 go run client/main.go