ProtoBuf — Golang 简单的例子

Squall_峰 · · 1475 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

greet.proto

syntax = "proto3";

package greet;

option go_package = "greetpb";

message Greeting {
    string first_name = 1;
    string last_name = 2;
}

message GreetRequest {
    Greeting greeting = 1;
}

message GreetResponse {
    string result = 1;
}

message GreetManytimesRequest {
    Greeting greeting = 1;
}

message GreetManytimesResponse {
    string result = 1;
}

message LongGreetRequest {
    Greeting greeting = 1;
}

message LongGreetResponse {
    string result = 1;
}

message GreetEveryRequest {
    Greeting Greeting = 1;
}

message GreetEveryResponse {
    string result = 1;
}

service GreetService{
    //Unary
    rpc Greet (GreetRequest) returns (GreetResponse) {};

    // server stream
    rpc GreetManytimes (GreetManytimesRequest) returns (stream GreetManytimesResponse) {};

    //client stream
    rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};

    // Bi-Directional Streaming
    rpc GreetEvery (stream GreetEveryRequest) returns (stream GreetEveryResponse);
}

输出成golang

#!/bin/bash
protoc greet/greetpb/greet.proto --go_out=plugins=grpc:.

Service

package main

import (
    "context"
    "fmt"
    "io"
    "log"
    "myproject/goGrpc_course/greet/greetpb"
    "net"
    "strconv"
    "time"

    "google.golang.org/grpc"
)

type server struct{}

// 接收客户端 cli.Greet 方法的 request
func (*server) Greet(ctx context.Context, req *greetpb.GreetRequest) (*greetpb.GreetResponse, error) {
    fmt.Println("Greet function was invoked with: ", req)
    firstName := req.GetGreeting().GetFirstName()
    result := "Hello" + firstName
    rst := &greetpb.GreetResponse{
        Result: result,
    }

    return rst, nil
}

// 接收客户端 cli.GreetManytimes 方法的 request
func (*server) GreetManytimes(req *greetpb.GreetManytimesRequest, stream greetpb.GreetService_GreetManytimesServer) error {
    fmt.Println("GreetManytimes function was invoked with:", req)
    firstName := req.GetGreeting().GetFirstName()
    for i := 0; i < 10; i++ {
        result := "Hello" + firstName + "number" + strconv.Itoa(i)
        resp := &greetpb.GreetManytimesResponse{
            Result: result,
        }
        stream.Send(resp)
        time.Sleep(1000 * time.Millisecond)
    }
    return nil
}

// 接收客户端 cli.LongGreet 方法的 request
func (*server) LongGreet(stream greetpb.GreetService_LongGreetServer) error {
    fmt.Println("LongGreet function was invoked with:", stream)
    result := ""
    // 循环接收若干 stream.send() 的请求
    for {
        req, err := stream.Recv()
        // 全部接收完毕:一次回应全部 result
        if err == io.EOF {
            fmt.Println("finished reading client stream")
            // SendAndClose 函数 return 了 error
            return stream.SendAndClose(&greetpb.LongGreetResponse{
                Result: result,
            })
        }
        if err != nil {
            log.Fatalln("reading client stream error: ", err)
        }
        firstName := req.GetGreeting().GetFirstName()
        result += "Hello " + firstName + "! "
    }
}

func (*server) GreetEvery(stream greetpb.GreetService_GreetEveryServer) error {
    fmt.Println("GreetEvery function was invoked with streaming request:")
    for {
        req, err := stream.Recv()
        if err == io.EOF {
            return nil
        }
        if err != nil {
            log.Fatalln("Error while reading client stream")
            return err
        }
        firstName := req.GetGreeting().GetFirstName()
        result := "Hello " + firstName + "! "
        // 发送应答
        if err := stream.Send(&greetpb.GreetEveryResponse{
            Result: result,
        }); err != nil {
            log.Fatalf("Error while sending datea to client: %v", err)
            return err
        }
    }
}

func main() {
    fmt.Println("Hello I'm servers!")
    // 50051 是 gRPC 的默认端口
    lst, err := net.Listen("tcp", "0.0.0.0:50051")
    if err != nil {
        log.Fatalf("Failed to listen: %v", err)
    }

    //创建 server 并注册
    s := grpc.NewServer()
    greetpb.RegisterGreetServiceServer(s, &server{})

    // 启动server
    if err := s.Serve(lst); err != nil {
        log.Fatalln("failed to serve: ", err)
    }
}

client

package main

import (
    "context"
    "fmt"
    "io"
    "log"
    "myproject/goGrpc_course/greet/greetpb"
    "time"

    "google.golang.org/grpc"
)

func main() {
    fmt.Println("Hello, I'm a client")
    //创建客户端拨号连接
    cc, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalln("could not connect: ", err)
    }
    defer cc.Close()

    //创建 client API 实例
    cli := greetpb.NewGreetServiceClient(cc)

    // doUnary(cli)
    // doServerStream(cli)
    // doClientStream(cli)
    doBiDiStream(cli)
}

func doUnary(cli greetpb.GreetServiceClient) {
    fmt.Println("starting do Unary RPC...")
    // request 内容(填写结构体)
    req := &greetpb.GreetRequest{
        Greeting: &greetpb.Greeting{
            FirstName: "Squall",
            LastName:  "Dong",
        },
    }
    //向服务器端的 Greet 方法传递数据
    resp, err := cli.Greet(context.Background(), req)
    if err != nil {
        log.Fatalln("Greet is failed", err)
    }
    log.Printf("Response form Greet:", resp.Result)

}

func doServerStream(cli greetpb.GreetServiceClient) {
    fmt.Println("starting doServerStream RPC...")
    rst := &greetpb.GreetManytimesRequest{
        Greeting: &greetpb.Greeting{
            FirstName: "Squall",
            LastName:  "dong",
        },
    }
    // 向服务器端的 GreetManytimes 方法传递数据
    respStream, err := cli.GreetManytimes(context.Background(), rst)
    if err != nil {
        log.Fatalln("Failed with calling GreetManytimes RPC: ", err)
    }
    for {
        msg, err := respStream.Recv()
        if err == io.EOF {
            fmt.Println("reached the end of the stream !")
            break
        }
        if err != nil {
            log.Fatalln("failed while recv message: ", err)
        }
        fmt.Println("Response from GreetManytimes: ", msg.GetResult())
    }
}

func doClientStream(cli greetpb.GreetServiceClient) {
    fmt.Println("starting doClientStream RPC...")
    // 向服务器端的 LongGreet 方法传递数据
    stream, err := cli.LongGreet(context.Background())
    if err != nil {
        log.Fatalln("send client stream failed : ", err)
    }
    // 创建需要发送的 stream 列表
    requests := []*greetpb.LongGreetRequest{
        &greetpb.LongGreetRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Squall",
            },
        },
        &greetpb.LongGreetRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Evin",
            },
        },
        &greetpb.LongGreetRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Emily",
            },
        },
        &greetpb.LongGreetRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Kimbarly",
            },
        },
        &greetpb.LongGreetRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Fanny",
            },
        },
    }

    // 循环发送
    for _, req := range requests {
        fmt.Printf("sending request: %v\n", req)
        stream.Send(req)
        time.Sleep(1000 * time.Millisecond)
    }
    // 发送完毕,关闭steam并接收相应
    resp, err := stream.CloseAndRecv()
    if err != nil {
        log.Fatalln("error while receiving response form LongGreet: ", err)
    }
    // 查看服务器的相应
    fmt.Println("LogGreeting response:", resp.GetResult())
    // resp.GetResult()

}

func doBiDiStream(cli greetpb.GreetServiceClient) {
    fmt.Println("starting doBiDiStream RPC")
    // create a stream by invoking the client
    stream, err := cli.GreetEvery(context.Background())
    if err != nil {
        log.Fatalln("Error while send client stream ", err)
    }
    // request := []*greetpb.GreetEveryRequest{
    //  &greetpb.GreetEveryRequest{
    //      Greeting: greetpb.Greeting{
    //          FirstName: "Squall",
    //      }
    //  }
    // }
    // stream.Send(&greetpb.GreetEveryRequest)

    requests := []*greetpb.GreetEveryRequest{
        &greetpb.GreetEveryRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Squall",
            },
        },
        &greetpb.GreetEveryRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Kevin",
            },
        },
        &greetpb.GreetEveryRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Emily",
            },
        },
        &greetpb.GreetEveryRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Kimbarly",
            },
        },
        &greetpb.GreetEveryRequest{
            Greeting: &greetpb.Greeting{
                FirstName: "Fanny",
            },
        },
    }

    waitc := make(chan struct{})

    // send a bunch of message to the client(go routine)
    go func() {
        for _, req := range requests {
            fmt.Printf("sending message: %v\n", req)
            stream.Send(req)
            time.Sleep(1000 * time.Millisecond)
        }
        stream.CloseSend()
    }()

    // receive a bunch of message from the client (go routine)
    go func() {
        for {
            res, err := stream.Recv()
            if err == io.EOF {
                break
            }
            if err != nil {
                log.Fatalln("Error while recving: ", err)
                break
            }
            fmt.Printf("Received: %v\n", res.GetResult())
        }
        close(waitc)
    }()

    // block until everything is done
    <-waitc
}

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:Squall_峰

查看原文:ProtoBuf — Golang 简单的例子

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1475 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传