学习 Golang 并入门 gRPC

用golang创建一个使用gRPC的原型的步骤。

我将这篇文章作为参考,并且在写代码的时候参考了该文章。这篇文章的代码与上述文章相同。它还更清楚地指出了在哪里编写代码以及protoc命令。

我在使用gvm来管理Go的版本。
Go的版本是 go version go1.16.5 darwin/amd64。

请使用protoc命令,并在以下位置进行安装。

在以下方面,gRPC有哪些优点

项目的准备

我会制作一个合适的项目。

go mod init example.com/cat

我将安装必要的软件包。

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

可以创建这种类型的go.mod文件。

module example.com/cat

go 1.16

require (
    github.com/golang/protobuf v1.5.2 // indirect
    golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
    golang.org/x/sys v0.0.0-20210816032535-30e4713e60e3 // indirect
    golang.org/x/text v0.3.7 // indirect
    google.golang.org/genproto v0.0.0-20210813162853-db860fec028c // indirect
    google.golang.org/grpc v1.40.0 // indirect
    google.golang.org/protobuf v1.27.1 // indirect
)

创建目录

请按以下方式创建文件夹和文件。

client/main.go
proto/cat.proto
server/main.go
service/main.go

首先,我们将proto/cat.proto写成以下格式。

syntax = "proto3";

option go_package = "./;pb";

package cat;

service Cat {
    rpc GetMyCat (GetMyCatMessage) returns (MyCatResponse) {}
}

message GetMyCatMessage {
    string target_cat = 1;
}

message MyCatResponse {
    string name = 1;
    string kind = 2;
}

关于 go_package 选项,需要将 package 的导入路径赋给 xx.proto 文件,可以通过执行 protoc 命令或在 .proto 文件中进行描述来实现。推荐的做法是写在 xx.proto 文件中。

相关链接:
– https://github.com/techschool/pcbook-go/issues/3#issuecomment-824040393
– https://blog.ebiiim.com/posts/grpc-with-go-mod/

请注意,以上提供的链接为活动URL。

代码自动生成

根据此proto/cat.proto文件,使用protoc命令自动生成gRPC代码。

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/cat.prot

生成客户端和服务器代码的方法可以在参考链接https://grpc.io/docs/languages/go/basics/#generating-client-and-server-code中找到。

使用这个命令

    • proto/cat_grpc.pb.go

 

    proto/cat.pb.go

«生成后,proto/cat_grpc.pb.go文件中还会生成一个名为mustEmbedUnimplementedCatServer()的方法,其内容如下。»

type CatServer interface {
    GetMyCat(context.Context, *GetMyCatMessage) (*MyCatResponse, error)
    mustEmbedUnimplementedCatServer()
}

由于这个方法的存在,我无法运行这次参考的实现,所以我会稍微修改自动生成命令,以防止生成以上提到的方法。

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=require_unimplemented_servers=false:. --go-grpc_opt=paths=source_relative proto/cat.proto

请提供更多上下文的信息,这样我才能更好地进行翻译。

    • https://github.com/grpc/grpc-go/issues/3794#issuecomment-725860916

 

    https://sat8bit.github.io/logs/daily-2021-01-28/

服务

package service

import (
    "context"
    "errors"

    pb "example.com/cat/proto"
)

type MyCatService struct {
}

func (s *MyCatService) GetMyCat(ctx context.Context, message *pb.GetMyCatMessage) (*pb.MyCatResponse, error) {
    switch message.TargetCat {
    case "tama":
        //たまはメインクーン
        return &pb.MyCatResponse{
            Name: "tama",
            Kind: "mainecoon",
        }, nil
    case "mike":
        //ミケはノルウェージャンフォレストキャット
        return &pb.MyCatResponse{
            Name: "mike",
            Kind: "Norwegian Forest Cat",
        }, nil
    }
return nil, errors.New("Not Found YourCat")
}

func (s *MyCatService) UnimplementedGreeterServer() {}

客户 (kè hù)

package main

import (
    "context"
    "fmt"
    "log"

    pb "example.com/cat/proto"

    "google.golang.org/grpc"
)
func main() {
    //sampleなのでwithInsecure
    conn, err := grpc.Dial("127.0.0.1:19003", grpc.WithInsecure())
    if err != nil {
        log.Fatal("client connection error:", err)
    }
    defer conn.Close()
    client := pb.NewCatClient(conn)
    message := &pb.GetMyCatMessage{TargetCat: "tama"}
    res, err := client.GetMyCat(context.TODO(), message)
    fmt.Printf("result:%#v \n", res)
    fmt.Println("---------")
    fmt.Printf("error::%#v \n", err)
}

服务器

package main

import (
    "log"
    "net"

    "example.com/cat/service"

    pb "example.com/cat/proto"

    "google.golang.org/grpc"
)
func main() {
    listenPort, err := net.Listen("tcp", ":19003")
    if err != nil {
        log.Fatalln(err)
    }
    server := grpc.NewServer()
    catService := &service.MyCatService{}
    // 実行したい実処理をseverに登録する
    pb.RegisterCatServer(server, catService)
    server.Serve(listenPort)
}

试一试

我会在终端中使用两个进程。

首先,我会把以下内容内化。

go run server/main.go 

接下来,使用另一个进程访问服务器。

go run client/main.go 

在client/main.go文件中,您可以看到以下的输出。

result:&pb.MyCatResponse{state:impl.MessageState{NoUnkeyedLiterals:pragma.NoUnkeyedLiterals{}, DoNotCompare:pragma.DoNotCompare{}, DoNotCopy:pragma.DoNotCopy{}, atomicMessageInfo:(*impl.MessageInfo)(0xc0000e5a08)}, sizeCache:0, unknownFields:[]uint8(nil), Name:"tama", Kind:"mainecoon"} 
---------
error::<nil> 

如果只想获取tama,请按以下方式进行更改。

fmt.Printf("result:%#v \n", res.Name)

请参阅

    • https://note.com/dd_techblog/n/nb8b925d21118

 

    • https://tech.smartcamp.co.jp/entry/grpc-and-protobuf-servey

 

    https://developers.google.com/protocol-buffers/docs/proto3#unknowns
广告
将在 10 秒后关闭
bannerAds