go get github.com/go-kit/kit
;go get github.com/gorilla/mux
;.
├── pb
│ └── hello.proto
├── cmd
│ └── server
│ └── main.go
├── pkg
│ ├── endpoint.go
│ ├── service.go
│ └── transport.go
└── go.mod
编写协议文件在 pb
目录下创建 hello.proto
文件,内容如下:
protobufCopy code
syntax = "proto3";
package pb;
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string message = 1;
}
HelloService
的服务,该服务只有一个方法 SayHello
,它需要一个 HelloRequest
参数并返回一个 HelloResponse
结构体。在项目根目录下运行以下命令生成 gRPC 代码(生成代码在pb文件夹目录下):
protoc --go-grpc_out=./pb --go_out=./pb ./pb/hello.proto
# 以下是生成的文件
─ pb
├── hello.pb.go
├── hello.proto
└── hello_grpc.pb.go
main.go
package main
import (
"fmt"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"google.golang.org/grpc"
pb "kit-grpc/pb"
"kit-grpc/pkg"
"net"
"os"
)
func main() {
logger := log.NewLogfmtLogger(os.Stderr)
ln, err := net.Listen("tcp", "127.0.0.1:9090")
if err != nil {
level.Error(logger).Log("err", err)
os.Exit(-1)
}
endpoints := pkg.MakeEndpoints(pkg.HelloService{})
grpcServer := pkg.NewGRPCServer(endpoints, logger)
grpc := grpc.NewServer()
pb.RegisterHelloServiceServer(grpc, grpcServer)
err = grpc.Serve(ln)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
service.go
package pkg
import "context"
type Service interface {
SayHello(ctx context.Context, name string) (string, error)
}
type HelloService struct{}
func (s HelloService) SayHello(ctx context.Context, name string) (string, error) {
return "Hello, " + name + "!", nil
}
endpoint.go
package pkg
import (
"context"
"github.com/go-kit/kit/endpoint"
pb "kit-grpc/pb"
)
type Endpoints struct {
SayHello endpoint.Endpoint
}
func MakeEndpoints(s Service) Endpoints {
return Endpoints{
SayHello: makeSayHelloEndpoint(s),
}
}
func makeSayHelloEndpoint(s Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(*pb.HelloRequest)
res, err := s.SayHello(ctx, req.Name)
if err != nil {
return nil, err
}
return pb.HelloResponse{
Message: res,
}, nil
}
}
transport.go
package pkg
import (
"context"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/transport/grpc"
pb "kit-grpc/pb"
)
func NewGRPCServer(endpoints Endpoints, logger log.Logger) pb.HelloServiceServer {
options := []grpc.ServerOption{}
return &grpcServer{
sayHello: grpc.NewServer(
endpoints.SayHello,
decodeHelloRequest,
encodeHelloResponse,
options...,
),
}
}
func decodeHelloRequest(_ context.Context, request interface{}) (interface{}, error) {
req := request.(*pb.HelloRequest)
return &pb.HelloRequest{Name: req.Name}, nil
}
func encodeHelloResponse(_ context.Context, response interface{}) (interface{}, error) {
res := response.(pb.HelloResponse)
return &pb.HelloResponse{Message: res.Message}, nil
}
type grpcServer struct {
pb.UnimplementedHelloServiceServer
sayHello grpc.Handler
}
func (s *grpcServer) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
_, resp, err := s.sayHello.ServeGRPC(ctx, req)
if err != nil {
return nil, err
}
return resp.(*pb.HelloResponse), nil
}
/**
* @date: 2023/2/19
* @desc:
*/
package main
import (
"context"
"google.golang.org/grpc"
pb "kit-grpc/pb"
"log"
)
func main() {
conn, err := grpc.Dial("127.0.0.1:9090", grpc.WithInsecure())
if err != nil {
log.Fatal("failed to dial server: ", err)
}
defer conn.Close()
client := pb.NewHelloServiceClient(conn)
resp, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "Alice"})
if err != nil {
log.Fatal("failed to call SayHello: ", err)
}
log.Println(resp.Message)
}