安装 protobuf
假设环境下已有protoc
(protocal buffers compiler)。
对于 Go 语言,安装相应的可执行文件:
go install google.golang.org/grpc/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
在Windows中,执行完安装命令后在C:\Users\user\go\bin
路径下会有proctoc-gen-go.exe
和protoc-gen-go-grpc.exe
。
安装完Go插件后,我们希望protoc生成Go语言的代码,需要为 .proto
文件加一行以指定生成的Go包名:
syntax = "proto3";
package com.example.pkg
option go_package = "example/gopkg"
如果需要使用 grpc
服务,安装包:
go get google.golang.org/grpc
之后便可启动一个 gRPC 服务器:
gRPC gateway
为 gRPC
服务生成面向 RestFul API
的网关
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest
syntax = "proto3";
package com.example.pkg
import "google/api/annotations.proto";
option go_package = "example/gopkg
service AuthService {
rpc Login(LRequest) returns (LResponse) {
option (google.api.http) = {
post: "/v1/login"
body: "*"
};
}
message LRequest {
string field = 1;
}
message LResponse {
string field = 1;
}
之后便可以生成grpc gateway的代码了:
protoc --go_out=. --go-grpc_out=. \
--grpc-gateway_out=. \
--openapiv2_out=. \
greeter.proto
其所生成的文件含义如下:
- greeter.pb.go: Protobuf message definitions.
- greeter_grpc.pb.go: gRPC service definitions.
- greeter.pb.gw.go: gRPC Gateway reverse-proxy code.
- greeter.swagger.json: OpenAPI (Swagger) documentation.
gRPC 服务
package main
import (
"context"
"fmt"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
pb "github.com/yourusername/yourproject/gen/go/hello"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
return &pb.HelloResponse{Message: fmt.Sprintf("Hello, %s!", req.Name)}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
reflection.Register(s)
log.Println("gRPC server is running on :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
gRPC 网关
package main
import (
"context"
"log"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
pb "github.com/yourusername/yourproject/gen/go/hello"
)
func runGateway() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithInsecure()}
err := pb.RegisterGreeterHandlerFromEndpoint(ctx, mux, "localhost:50051", opts)
if err != nil {
log.Fatalf("failed to register gateway: %v", err)
}
log.Println("gRPC Gateway is running on :8080")
if err := http.ListenAndServe(":8080", mux); err != nil {
log.Fatalf("failed to serve gateway: %v", err)
}
}
func main() {
go runGateway()
// 启动 gRPC 服务
runGRPCServer()
}