Skip to content

go中grpc的使用

1. install go

2. install protocol buffer compiler here

3. install go plugins

shell
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

4. write proto file

protobuf
syntax = "proto3";

// 解析为go可调用包 可选用参数
option go_package = ".;helloworld";

// 定义服务
service RouteGuide {
    // 定义方法 普通模式
    rpc GetFeature(Point) returns (Feature) {}
    // 服务端流模式 服务端向客户端推流
    rpc GetServeStream(Point) returns (stream Feature){}
    // 客户端流模式 客户端向服务端推流
    rpc PutServeStream(stream Point) returns (Feature){}
    // 双向流模式 服务端客户端双向推流
    rpc AllServeStream(stream Point) returns (stream Feature){}
}

message Point {
    int32 x = 1;
    int32 y = 2;
}

message Feature {
    int32 z = 3;
}

5. compiler

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative xxxx/xxx.proto

6. 编辑server

go
// GolangDocs/src/grpc/server/server.go
package main

import (
    "context"
    "fmt"
    "gogrpctoturial/helloworld"
    "google.golang.org/grpc"
    "net"
    "sync"
    )

type Server struct {
    helloworld.UnimplementedRouteGuideServer
}

// GetFeature 普通模式
func (s Server) GetFeature(ctx context.Context, point *helloworld.Point) (*helloworld.Feature, error) {
    val := point.GetX() + point.GetY()
    return &helloworld.Feature{Z: val}, nil
}

// GetServeStream 服务端流模式
    func (s Server) GetServeStream(point *helloworld.Point, serverStr helloworld.RouteGuide_GetServeStreamServer) error {
    val := point.GetX() + point.GetY()
    for i := 0; i < 10; i++ {
        val += int32(i)
        err := serverStr.Send(&helloworld.Feature{Z: val})
        if err != nil {
            return err
        }
    }
    return nil
}

// PutServeStream 客户端流模式
    func (s Server) PutServeStream(clientStr helloworld.RouteGuide_PutServeStreamServer) error {
    for {
        recv, err := clientStr.Recv()
        if err != nil {
            break
        }
        fmt.Printf("客户端流模式 current point x:%d y:%d\n", recv.GetX(), recv.GetY())
    }
    return nil
}

// AllServeStream 双向流模式
func (s Server) AllServeStream(allStr helloworld.RouteGuide_AllServeStreamServer) error {
    var wg = sync.WaitGroup{}
    wg.Add(2)

    // recv
    go func() {
        for {
            recv, err := allStr.Recv()
            if err != nil {
                break
            }
            fmt.Printf("双向流模式 current point x:%d y:%d\n", recv.GetX(), recv.GetY())
        }
    }()

    // send
    go func() {
        for i := 0; i < 10; i++ {
            err := allStr.Send(&helloworld.Feature{Z: int32(i)})
            if err != nil {
                break
            }
        }
    }()
    wg.Wait()
    return nil
}

func main() {
    g := grpc.NewServer()
    helloworld.RegisterRouteGuideServer(g, &Server{})
    listen, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println(err)
        return
    }
    err = g.Serve(listen)
    if err != nil {
        return
    }
}

7. 编辑client

go
// GolangDocs/src/grpc/client/client.go
package main

import (
    "context"
    "fmt"
    "gogrpctoturial/helloworld"
    "google.golang.org/grpc"
    "sync"
    )

func main() {
    conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer conn.Close()

    c := helloworld.NewRouteGuideClient(conn)

    // 普通模式
    feature, err := c.GetFeature(context.Background(), &helloworld.Point{
        X: 12,
        Y: 22,
    })
    if err != nil {
        return
    }
    fmt.Println(feature.GetZ())

    // 服务端流模式
    Serverstream, err := c.GetServeStream(context.Background(), &helloworld.Point{
        X: 100,
        Y: 2,
    })
    if err != nil {
        return
    }
    for i := 0; i < 10; i++ {
        recv, err := Serverstream.Recv()
        if err != nil {
            break
        }
        fmt.Printf("服务端流模式 current point feature value: %d\n", recv.GetZ())
    }

    // 客户端流模式
    Clientstream, err := c.PutServeStream(context.Background())
    if err != nil {
        return
    }
    for i := 0; i < 10; i++ {
        err := Clientstream.Send(&helloworld.Point{
            X: int32(i),
            Y: 1,
        })
        if err != nil {
            break
        }
    }

    // 双向流模式
    Allstream, err := c.AllServeStream(context.Background())
    if err != nil {
        return
    }
    var wg = sync.WaitGroup{}
    wg.Add(2)

    // recv
    go func() {
        defer wg.Done()
        for {
            recv, err := Allstream.Recv()
            if err != nil {
                break
            }
            fmt.Printf("双向流模式 current point feature value: %d\n", recv.GetZ())
        }
    }()

    // send
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            err := Allstream.Send(&helloworld.Point{
                X: int32(i),
                Y: 7,
            })
            if err != nil {
                break
            }
        }
    }()
    wg.Wait()
}

最后更新: