go+grpc示例

我使用的GoLand编辑器。

1. 概述

使用go+gRPC实现 Hello World。

2. 安装软件

2.1 windows安装protoc

  1. 下载地址: https://github.com/protocolbuffers/protobuf/releases
  2. 将页面拉到底部,查找 xxx-win64.zip,为windows系统所使用的,下载
  3. 解压zip后,将protoc的的bin目录添加的系统环境变量的Path中,以便能使用protoc命令
  4. 在命令行中验证
protoc --version

能看到版本信息

2.2 安装Go protobuf插件

使用如下命令:

go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get -u google.golang.org/protobuf

2.3 安装grpc-go

go get -u google.golang.org/grpc

3. 编写Hello World示例

操作顺序

  1. 创建目录结构
  2. ide安装protobuf插件,实现语法高亮
  3. 编写服务端 .proto文件
  4. 根据proto文件生成代码
  5. 编写服务端提供接口代码
  6. 编写客户端调用接口的代码

3.1 目录结构

go-grpc
│  go.mod
│  go.sum   
├─go_client
│  │  main.go
│  │  
│  └─proto
│      └─hello
│              hello.pb.go
│              
└─go_server
    │  main.go
    │  
    ├─controller
    │  └─hello_controller
    │          hello_server.go
    │          
    └─proto
        └─hello
                hello.pb.go
                hello.proto

3.2 ide安装protobuf插件,实现语法高亮

File->Settings->Plugins->Marketplace,搜索Protocol Buffers,安装后不需要重启

3.3 编写hello.proto文件

//指定proto版本
syntax = "proto3";
//指定包名
package hello;
option go_package="./hello";

//定义Hello服务
service Hello{
  //定义SayHello方法
  rpc SayHello(HelloRequest) returns (HelloResponse){}
  //定义LotsOfReplies方法
  rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}
}

//HelloRequest请求结构
message HelloRequest{
  string name = 1;
}
//HelloResponse响应结构
message HelloResponse{
  string message = 1;
}

3.4 生成代码

执行如下命令:

protoc -I . --go_out=plugins=grpc:. ./hello.proto

将生成的代码复制到go_server、go_client的自定义目录中

3.5 编写服务端提供接口的代码

// hello_server.go
package hello_controller

import (
    "context"
    "fmt"
)
import "go-grpc/go_server/proto/hello"

type HelloController struct {

}

func (h *HelloController) SayHello(ctx context.Context, in  *hello.HelloRequest) (*hello.HelloResponse, error){
    return &hello.HelloResponse{Message : fmt.Sprintf("%s", in.Name)}, nil
}

func (h *HelloController) LotsOfReplies(in *hello.HelloRequest, stream hello.Hello_LotsOfRepliesServer)  error{
    for i := 0; i < 10; i++ {
        stream.Send(&hello.HelloResponse{
            Message: fmt.Sprintf("%s %s %d", in.Name, "Reply", i),
        })
    }
    return nil
}
// main.go
package main

import (
    "go-grpc/go_server/controller/hello_controller"
    "go-grpc/go_server/proto/hello"
    "google.golang.org/grpc"
    "log"
    "net"
)

const Address = "0.0.0.0:9090"

func main() {
    listen, err := net.Listen("tcp", Address)
    if err != nil {
        log.Fatal("Failed to listen: %v", err)
    }
    s := grpc.NewServer()
    //服务注册
    hello.RegisterHelloServer(s, &hello_controller.HelloController{})
    log.Println("Listen on " + Address)
    err = s.Serve(listen)
    if err != nil {
        log.Fatalf("Failed to serve: %v", err)
    }
}

进入go_server目录,运行main:

go run .

能看到日志输出。

3.6 编写客户端请求接口的代码

package main

import (
    "context"
    "go-grpc/go_server/proto/hello"
    "google.golang.org/grpc"
    "io"
    "log"
)

const Address = "0.0.0.0:9090"

func main() {
    conn, err := grpc.Dial(Address, grpc.WithInsecure())
    if err != nil {
        log.Fatalln(err)
    }
    //一定执行
    defer conn.Close()
    //初始化客户端
    c := hello.NewHelloClient(conn)
    //调用SayHello方法
    res, err := c.SayHello(context.Background(), &hello.HelloRequest{Name: "Hello World"})
    if err != nil {
        log.Fatalln(err)
    }
    log.Println(res.Message)
    //调用LotsOfReplies方法
    stream, err := c.LotsOfReplies(context.Background(), &hello.HelloRequest{Name: "Hello World"})
    if err != nil {
        log.Fatalln(err)
    }
    for true {
        res, err := stream.Recv()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Printf("stream.Recv: %v", err)
        }
        log.Printf("%s", res.Message)
    }
}

进入go_client目录,运行main:

go run .

能看到正常日志输出。

4. 总结

除了翻墙问题外,整体还是比较简单的

你可能感兴趣的:(go+grpc示例)