# GRPC

## 官方网站

{% embed url="<https://grpc.io/>" %}

## 项目地址

{% embed url="<https://github.com/grpc/grpc-go>" %}

## 下载与安装

首先安装`protoc`

访问下方地址

{% embed url="<https://github.com/protocolbuffers/protobuf/releases>" %}

根据系统类型找到合适的安装包下载后解压，将其中的二进制文件移入`$PATH`目录中，将其中的`include/`目录下的文件复制到`/usr/local/lib/`目录下

接着安装 protoc-gen-go 插件

```bash
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
```

最后下载 grpc 库

```bash
go get -u google.golang.org/grpc
```

如果无法访问外网则使用以下方式

```bash
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
git clone git@github.com:googleapis/go-genproto.git $GOPATH/src/google.golang.org/genproto
```

## 例子

### 简单grpc服务

{% tabs %}
{% tab title="server/main.go" %}

```go
package main

import (
	"context"
	"log"
	"net"

	"google.golang.org/grpc"
	
	"demo/rpc/grpc/simple/protos/pb"
)

const (
	port = "localhost:9090"
)

type server struct{}

func (s *server) Echo(ctx context.Context, in *pb.StringMessage) (*pb.StringMessage, error) {
	log.Printf("Received: %v", in.Value)
	return &pb.StringMessage{Value: "Hello " + in.Value}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterYourServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

```

{% endtab %}

{% tab title="client/main.go" %}

```go
package main

import (
	"context"
	"log"
	"os"
	"time"

	"google.golang.org/grpc"
	
	"demo/rpc/grpc/simple/protos/pb"
)

const (
	address     = "localhost:9090"
	defaultName = "world"
)

func main() {
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewYourServiceClient(conn)

	name := defaultName
	if len(os.Args) > 1 {
		name = os.Args[1]
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.Echo(ctx, &pb.StringMessage{Value: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.Value)
}

```

{% endtab %}

{% tab title="protos/helloworld.proto" %}

```
syntax = "proto3";
option go_package = "/pb";

package example;

message StringMessage {
  string value = 1;
}

service YourService {
  rpc Echo(StringMessage) returns (StringMessage) {}
}
```

{% endtab %}
{% endtabs %}

执行命令

```
protoc --go_out=./protos --go-grpc_out=./protos --proto_path=./protos protos/*.proto
```

这时 protos/ 目录下会生成 helloworld.pb.go 和 helloworld\_grpc.pb.go 文件，该文件是 grpc 接口以及相关参数的定义

执行以下命令启动GRPC服务端

```bash
go run server/main.go
```

执行以下命令执行GRPC客户端

```
go run client/main.go
```

服务端输出

```
2019/06/25 17:32:09 Received: world
```

客户端输出

```
2019/06/25 17:32:09 Greeting: Hello world
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://golang-2.gitbook.io/handbook/avanced/rpc/grpc.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
